npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@revoengine/sdk

v1.6.7

Published

Official Node.js SDK for the RevoEngine Platform

Readme

@revoengine/sdk

Official Node.js SDK for RevoEngine. It provides the modern api, utils, storage, transport, vault, serviceAccount, and agents namespaces, top-level execute(), and the batch controller in both Revo-hosted CUSTOM_NODEJS components and standalone Node.js applications.

Requirements: Node.js 22 or newer.

Development and GitLab CI use Node.js 24.21.0. Run nvm use to select the checked-in .nvmrc.

SDK 1.6.7 compatibility

This release synchronizes the complete public SDK contract with the current platform low-code declarations. Remote calls require a platform runtime that admits the bundled contract revision; publishing the SDK alone does not deploy that runtime. Use the SDK version supported by the target platform deployment until its contract is upgraded.

Storage declarations include physical-line reads, quote-disabled CSV dialects, per-record byte limits, and the opt-in onError: 'skipRow' read policy. That policy skips records with the wrong source column count and returns bounded locations in csvReport; syntax and record-size errors still abort. The report describes the whole source and must not be summed across pages.

HTTP Storage requests/responses now use requestType: 'storage' and responseType: 'storage', with flat Storage-only source / target objects. Legacy HTTP Files references and the old Storage stream mode are rejected. Byte/SSE response iterators remain local to V8 and are blocked by the SDK before network or hosted bridge dispatch. Automation schedules use { scheduleFor } options instead of positional dates. Regenerated types also include the current Storage and database contracts; use those declarations when migrating callers.

The transport namespace exposes sftpImport, sftpExport, and sftpCommands with active Secret names or IDs instead of inline credentials. Storage references use the same namespace and effective access rules as other file operations. Legacy SFTP helpers and the removed thread-goal methods are not exposed by the current SDK contract. Refer to the transfer guide for Secret formats and file-transfer examples.

SDK 1.6.7 retains portable Component digest declarations and one readable-relation contract for Databases, live Views, and Materialized Views. Use api.exportDatabase() for all three relation types. api.getDatabaseViewData() remains a deprecated read alias; api.exportDatabaseView() and separate REST View export operations are removed. Existing integrations should update these calls before rollout.

Database exports can select CSV, TSV, NDJSON, or XLSX. An asynchronous export returns its job ID for operation tracking. The import workflow starts with api.importDatabase(), then permits a reviewed mapping update and an explicit api.commitDatabaseImport() after preview validation. The generated declarations describe the current request and response shapes; the platform still enforces permissions and validates source and target state before committing an import.

Assistant model inputs follow the current platform: gpt-6.1-sol and gpt-6-luna; Fast mode is supported for Luna. Update older Sol model identifiers.

Remote MCP server configurations in this contract use public HTTPS destinations. Private-network access is not an accepted SDK setting; review the server URL, provider consent, Vault binding, and tool permissions before enabling a plugin.

Choose your runtime

| Environment | How to start | Authentication | | --- | --- | --- | | Revo-hosted CUSTOM_NODEJS | Export async function init(runtime) | Revo injects an execution-bound runtime; user code receives no API key. | | Standalone Node.js | Create new RevoClient(options) | Supply a RevoEngine API key explicitly or through an environment variable. |

Both modes expose the same api, utils, storage, transport, vault, serviceAccount, agents, execute, and batch properties, but return types reflect where the work happens:

| Call kind | Revo-hosted | Standalone | | --- | --- | --- | | Execution snapshot, cache, debug, and logging | Synchronous | Throws synchronously because no execution context exists | | Current user and instance | Synchronous injected snapshot | Asynchronous lazy /api/v1/me discovery | | Remote api, storage, transport, vault, serviceAccount, agents, and execute() calls | Asynchronous | Asynchronous | | Local utils and batch.configure() | Synchronous unless the utility is inherently asynchronous | Same |

Installation

Standalone applications install the SDK normally:

npm install @revoengine/sdk

New Revo-hosted components receive the exact platform-supported SDK version and a JSDoc RevoRuntime type import in their generated starter files. RevoEngine pins that version again in the deployment package and injects the runtime into the component entrypoint. Component code does not construct a RevoClient.

The platform chooses the hosted package version; publishing SDK 1.6.7 does not upgrade existing hosted deployments or their generated package pins.

Hosted user code receives neither a tenant API key nor the private runtime credential and does not perform /api/v1/me discovery. The generated parent worker owns the short-lived, execution-bound bridge. The @revoengine/sdk/hosted entrypoint is platform-internal and must not be imported by a component.

Revo-hosted CUSTOM_NODEJS

Basic entrypoint

Export a named init function. Do not construct RevoClient and do not call a separate initialization method.

/** @param {import('@revoengine/sdk').RevoRuntime} runtime */
export async function init(runtime) {
  const { api, utils, storage, vault, agents, execute, batch } = runtime;
  const { data: rows, next } = await api.getDatabaseData('Sales', {
    fields: ['saleId', 'customerId', 'total', 'createdAt'],
    sort: ['-createdAt'],
    take: 25,
  });

  const file = await storage.putObject({
    name: `sales-${utils.randomUUID()}.json`,
    data: JSON.stringify({ rows, next }),
    mimeType: 'application/json',
  });

  return {
    storageEntryId: file.storageEntryId,
    exportedRows: rows.length,
    hasNextPage: next,
  };
}

putObject() is appropriate here because this is a deliberately small JSON payload. Use an upload session for larger exports, as shown below.

Existing components that export async function init() remain compatible; JavaScript ignores the additional runtime argument.

Input, context, and secrets

Hosted context comes from the current execution snapshot and is synchronous, just like the low-code surface. Only platform-backed work returns a promise.

export async function init(runtime) {
  const { api } = runtime;
  const input = api.input();
  const currentUser = api.currentUser();
  const instance = api.getInstanceDetails();
  const signingSecret = await api.getSecret('WEBHOOK_SIGNING_SECRET');

  api.log({
    message: 'Processing custom component',
    args: {
      userId: currentUser.userId,
      instanceId: instance.id,
      hasInput: input != null,
    },
  });

  // Use the secret without returning or logging its value.
  return { accepted: Boolean(signingSecret) };
}

Execution-only methods such as api.input(), api.getContext(), api.getExecutionId(), and api.getOperationId() are available only in hosted executions.

Use runtime.execute(code, { readOnly: true }) for transient code that must not write platform state. readOnly: false selects full execution for an authorized standalone client; a hosted execution inherits its mode and cannot escalate a restricted parent.

Configure hosted batching

Configure batching before the first remote call:

export async function init(runtime) {
  runtime.batch.configure({
    failureMode: 'stop',
    maxCalls: 16,
    maxInFlight: 2,
  });

  const [customers, agents] = await Promise.all([
    runtime.api.getDatabaseData('Customers', { take: 100 }),
    runtime.agents.list(),
  ]);

  return {
    customers: customers.data,
    agents,
  };
}

batch.configure() is synchronous and rejects changes after the first remote batch has been dispatched.

Standalone Node.js

Basic client

Constructing RevoClient is synchronous and performs no network I/O. The first platform-backed call validates the API key through /api/v1/me, reads the instance bound to that key, discovers its Sandbox endpoint, and dispatches the queued runtime batch.

import { RevoClient } from '@revoengine/sdk';

const apiKey = process.env.REVO_API_KEY;
if (!apiKey) throw new Error('REVO_API_KEY is required.');

const revo = new RevoClient({
  apiKey,
});

type Sale = {
  saleId: string;
  customerId: string;
  total: number;
  createdAt: string;
};

const result = await revo.api.getDatabaseData<Sale>('Sales', {
  filter: { field: 'total', op: 'gte', value: 100 },
  sort: ['-createdAt'],
  take: 100,
});

console.log(result.data);

There is no init() or connection method.

Execute active low-code libraries

execute(code, options) runs one transient JavaScript or TypeScript component inside RevoEngine. The source has the normal low-code api and active tenant libs.* surface. Library functions and source never move into the Node.js process; only the JSON-serializable request and execution result cross the runtime transport.

Revo-hosted CUSTOM_NODEJS:

/** @param {import('@revoengine/sdk').RevoRuntime} runtime */
export async function init(runtime) {
  const customerId = runtime.api.input('customerId');
  const execution = await runtime.execute(
    `
      const customerId = api.input('customerId');
      const customer = await libs.Customers.Queries.get(customerId);
      const balance = await libs.Billing.Balance.current(customerId);
      return { customer, balance };
    `,
    {
      inputs: { customerId },
      timeoutMs: 10_000,
    },
  );

  return execution.results;
}

Standalone Node.js:

import { RevoClient } from '@revoengine/sdk';

const revo = new RevoClient({
  apiKey: process.env.REVO_API_KEY,
  executionDefaults: {
    timeoutMs: 60_000,
    memory: 256,
  },
});

type CustomerSummary = {
  customerId: string;
  name: string;
  balance: number;
};

const execution = await revo.execute<CustomerSummary>(
  `
    const customerId = api.input('customerId');
    return libs.Customers.Summary.build(customerId);
  `,
  {
    inputs: { customerId: 'customer-1' },
    timeoutMs: 10_000,
  },
);

console.log(execution.results);

JavaScript is selected with language: 'javascript'; TypeScript is the default. The default timeout is 60 seconds. Standalone executionDefaults set reusable language, timeout, or memory defaults, and per-call options override them. One execute() call creates one isolated execution. Put related libs.* operations in the same source when they belong to one workflow. Concurrent separate calls still use the SDK's automatic JSON-RPC batching but execute in separate isolates. Low-code runtime batches are not retried because source can perform writes.

Environment configuration

const revo = new RevoClient();

Supported environment aliases, in precedence order after explicit constructor options:

  • URL: REVO_URL, REVO_BASE_URL, REVOENGINE_URL, REVOENGINE_BASE_URL
  • API key: REVO_TOKEN, REVO_API_KEY, REVOENGINE_TOKEN, REVOENGINE_API_KEY

The default API URL is https://api.revoengine.com. The API key already identifies its instance, so RevoClient has no instance option and sends no separate instance header. /api/v1/me is the sole source of the bound instance identity and Sandbox endpoint.

Keep the API key in a server-side secret or environment variable. This SDK is for Node.js processes and must not be bundled into browser code with a key.

Explicit options always win:

const apiKey = process.env.REVO_API_KEY;
if (!apiKey) throw new Error('REVO_API_KEY is required.');

const revo = new RevoClient({
  baseUrl: 'https://api.revoengine.com',
  apiKey,
  requestTimeoutMs: 30_000,
  executionDefaults: {
    language: 'typescript',
    timeoutMs: 60_000,
    memory: 256,
  },
  batch: {
    failureMode: 'independent',
    maxCalls: 16,
    maxRequestBytes: 128 * 1024,
    maxInFlight: 2,
    maxQueuedCalls: 256,
  },
});

The SDK never reads or writes Revo CLI credential files.

Automatic batching

Calls queued in the same microtask are grouped. Promise.all is the normal way to issue a batch:

const [customers, crmToken, activeAgents] = await Promise.all([
  revo.api.getDatabaseData('Customers', { take: 100 }),
  revo.api.getSecret('CRM_API_TOKEN'),
  revo.agents.list(),
]);

Sequential await statements naturally produce separate batches:

const customers = await revo.api.getDatabaseData('Customers', { take: 100 });
const agents = await revo.agents.list();

The default independent mode executes every valid call and settles each promise independently. In stop mode calls execute in order; after one call fails, later calls in that batch reject with BATCH_STOPPED.

const revo = new RevoClient({
  batch: { failureMode: 'stop' },
});

Defaults are 32 calls per request, 256 KiB per request, four in-flight batches, and 1,024 queued calls. Client configuration can only lower server ceilings. The complete batch is validated before any call executes.

Runtime batches are never retried automatically because they may contain mutations. If transport is interrupted after dispatch, unresolved calls reject with RevoTransportError and indeterminate: true.

Batching is not a transaction. api.transactionDatabaseData is intentionally not part of the SDK.

Local utils

utils runs locally and is available before authentication or discovery:

const payload = JSON.stringify({ event: 'customer.updated' });
const secret = process.env.SIGNING_SECRET;
if (!secret) throw new Error('SIGNING_SECRET is required.');

const requestId = revo.utils.randomUUID();
const signature = revo.utils.hmac(payload, secret);
const encoded = revo.utils.encodeBase64('RevoEngine');

Only the modern first-class utility surface is exposed; deprecated low-code aliases are not included. utils.sleep(), utils.generateHash(), and utils.compareHash() remain asynchronous by design; the other local utilities return their values directly.

Runtime context

Hosted context reads are synchronous because the generated worker injects an immutable execution snapshot before init(runtime):

export async function init(runtime) {
  const input = runtime.api.input();
  const currentUser = runtime.api.currentUser();
  const instanceId = runtime.api.getCurrentInstance();

  runtime.api.log({
    message: 'Started',
    args: { userId: currentUser.userId, instanceId, hasInput: input != null },
  });

  return runtime.api.getSecret('SIGNING_SECRET');
}

The three standalone identity methods are asynchronous because their first call performs lazy /api/v1/me discovery and later calls use the cached profile:

const [currentUser, instanceId, instance] = await Promise.all([
  revo.api.currentUser(),
  revo.api.getCurrentInstance(),
  revo.api.getInstanceDetails(),
]);

Other context methods throw RevoRuntimeContextUnavailableError synchronously outside a hosted execution. The distinct RevoApi and RevoStandaloneApi types make the hosted snapshot and standalone discovery behavior explicit.

HTTP calls

api.httpCall(request, options) supports ordinary JSON/text/base64/document responses and HTTP-to-Storage transfers through both the standalone and hosted SDK:

const response = await revo.api.httpCall(
  { url: 'https://example.com/report.pdf', method: 'GET' },
  { responseType: 'storage', target: { name: 'report.pdf' } },
);
if (response.status >= 200 && response.status < 300 && response.storage) {
  console.log(response.storage.entry);
}

Use requestType: 'storage' with source: { storageEntryId } for a Storage request body. Request and response modes are independent. Source/target references are flat Storage objects; Files, nested storage and raw string identifiers are rejected. Targets can create an entry, replace it using { storageEntryId, replace: true }, or fill and finalize an existing empty direct session using { storageUploadSessionId }. Only 2xx responses write Storage; other statuses return bounded diagnostic data.

responseType: 'stream' (bytes/SSE) is deliberately absent from SDK declarations and rejects before discovery, queueing or transport, including the hosted CUSTOM_NODEJS bridge. Storage responses remain supported. Local low-code V8 and agent code_exec do support stream iterators: consume them inside the low-code body, then return bounded serializable data. An SDK execute(...) call may run such a body; it cannot return its iterator through the JSON transport.

Developing coordinated platform contracts

After regenerating platform declarations, synchronize this checkout with:

REVOENGINE_PLATFORM_PATH=/path/to/platform node scripts/sync-contract.mjs --working-tree
REVOENGINE_PLATFORM_PATH=/path/to/platform npm run contract:check -- --working-tree

Working-tree snapshots are explicitly unreleasable: the normal provenance/CI check continues to require committed platform sources. After committing the platform changes, run sync-contract.mjs without --working-tree, then run the normal contract:check against that pinned commit before releasing the SDK.

Storage

Small text or binary objects

storage.putObject() is convenient for small payloads that fit the runtime batch limit:

const settingsFile = await revo.storage.putObject({
  name: 'settings.json',
  data: JSON.stringify({ locale: 'pl-PL', enabled: true }),
  dataEncoding: 'utf8',
  mimeType: 'application/json',
});

async function uploadSmallPdf(pdfBuffer: Buffer) {
  return revo.storage.putObject({
    name: 'invoice.pdf',
    data: pdfBuffer.toString('base64'),
    dataEncoding: 'base64',
    mimeType: 'application/pdf',
  });
}

Large binary uploads

Large files must use an upload session or signed URL so their bytes do not enter the JSON runtime batch:

import type { RevoRuntime } from '@revoengine/sdk';

export async function uploadBinary(
  runtime: Pick<RevoRuntime, 'storage'>,
  name: string,
  contentType: string,
  bytes: Uint8Array,
) {
  const { session, upload } = await runtime.storage.createUploadSession({
    name,
    contentTypeHint: contentType,
    sizeHint: bytes.byteLength,
    uploadMode: 'direct',
  });

  const sessionId = session.storageUploadSessionId;

  try {
    if (!upload.uploadUrl) {
      throw new Error('RevoEngine did not return a direct upload URL.');
    }

    const headers = new Headers(upload.headers);
    if (!headers.has('content-type')) {
      headers.set('content-type', contentType);
    }

    const response = await fetch(upload.uploadUrl, {
      method: upload.method,
      headers,
      body: Buffer.from(bytes),
    });
    if (!response.ok) {
      throw new Error(`Upload failed with HTTP ${response.status}.`);
    }

    const { entry } = await runtime.storage.finalizeUploadSession(sessionId);
    return entry;
  } catch (error) {
    await runtime.storage.abortUploadSession(sessionId).catch(() => undefined);
    throw error;
  }
}

The helper accepts either a RevoClient or the runtime injected into hosted init(runtime). Session creation, finalization, and best-effort abort remain runtime calls; only the binary bytes bypass the JSON batch.

Excel export from database data

Install exceljs in your standalone application or add it to the hosted component's package.json dependencies.

import ExcelJS from 'exceljs';
import type { RevoRuntime } from '@revoengine/sdk';
import { uploadBinary } from './upload-binary.js';

type SaleRow = {
  saleId: string;
  customerId: string;
  total: number;
  createdAt: string;
};

type ExportRuntime = Pick<RevoRuntime, 'storage'> & {
  readonly api: Pick<RevoRuntime['api'], 'getDatabaseData'>;
};

export async function exportSales(
  runtime: ExportRuntime,
) {
  const workbook = new ExcelJS.Workbook();
  const sheet = workbook.addWorksheet('Sales');
  sheet.columns = [
    { header: 'Sale ID', key: 'saleId' },
    { header: 'Customer', key: 'customerId' },
    { header: 'Total', key: 'total' },
    { header: 'Created at', key: 'createdAt' },
  ];

  let skip = 0;
  for (;;) {
    const page = await runtime.api.getDatabaseData<SaleRow>('Sales', {
      fields: ['saleId', 'customerId', 'total', 'createdAt'],
      sort: { saleId: 'ASC' },
      take: 1_000,
      skip,
    });

    sheet.addRows(page.data);
    if (!page.next) break;
    if (page.results === 0) {
      throw new Error('Sales pagination did not advance.');
    }
    skip += page.results;
  }

  const bytes = Buffer.from(await workbook.xlsx.writeBuffer());
  return uploadBinary(
    runtime,
    'sales-export.xlsx',
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    bytes,
  );
}

Standalone call site:

import { RevoClient } from '@revoengine/sdk';
import { exportSales } from './export-sales.js';

const revo = new RevoClient();
const file = await exportSales(revo);
console.log(file.storageEntryId);

The same exporter can be used in Revo-hosted code:

import { exportSales } from './export-sales.js';

export async function init(runtime) {
  const file = await exportSales(runtime);
  return { storageEntryId: file.storageEntryId };
}

The stable unique sort makes offset pagination deterministic. If the table can change during export, filter on an immutable snapshot/version marker so later pages describe the same logical dataset.

PDF generation

Install pdfkit in your application or hosted component dependencies:

import PDFDocument from 'pdfkit';
import type { RevoRuntime } from '@revoengine/sdk';
import { uploadBinary } from './upload-binary.js';

function renderCustomerPdf(customer: unknown): Promise<Buffer> {
  return new Promise((resolve, reject) => {
    const document = new PDFDocument({ margin: 48 });
    const chunks: Buffer[] = [];

    document.on('data', (chunk: Buffer) => chunks.push(chunk));
    document.on('error', reject);
    document.on('end', () => resolve(Buffer.concat(chunks)));

    document.fontSize(18).text('Customer summary');
    document.moveDown();
    document.fontSize(10).text(JSON.stringify(customer, null, 2));
    document.end();
  });
}

type ExportRuntime = Pick<RevoRuntime, 'storage'> & {
  readonly api: Pick<RevoRuntime['api'], 'getDatabaseData'>;
};

export async function exportCustomer(
  runtime: ExportRuntime,
  customerId: string,
) {
  const { data } = await runtime.api.getDatabaseData('Customers', {
    filter: { field: 'customerId', op: 'eq', value: customerId },
    take: 1,
  });
  if (!data[0]) throw new Error(`Customer ${customerId} was not found.`);

  const pdf = await renderCustomerPdf(data[0]);
  return uploadBinary(runtime, `customer-${customerId}.pdf`, 'application/pdf', pdf);
}

Standalone call site:

import { RevoClient } from '@revoengine/sdk';
import { exportCustomer } from './export-customer.js';

const revo = new RevoClient();
const file = await exportCustomer(revo, 'customer-1');
console.log(file.storageEntryId);

Revo-hosted call site:

import { exportCustomer } from './export-customer.js';

export async function init(runtime) {
  const input = runtime.api.input();
  if (!input || typeof input.customerId !== 'string') {
    throw new Error('customerId input is required.');
  }
  const file = await exportCustomer(runtime, input.customerId);
  return { storageEntryId: file.storageEntryId };
}

Jobs and agents

const jobId = await revo.api.triggerJob(
  '8f1fe47f-90e6-4c16-a9ea-ccba5ca2a8da',
  { customerId: 'customer-1' },
);

const agents = await revo.agents.list();
const agentId = agents[0]?.agentId;
if (agentId) {
  const run = await revo.agents.startRun(agentId, {
    instruction: `Process the result of job ${jobId}.`,
    triggerType: 'REQUEST',
    triggerRefType: 'JOB',
    triggerRefId: jobId,
    state: { jobId },
  });
  console.log(run.agentRunId);
}

Available methods and request types are exported through the package's TypeScript declarations. The generated declarations are the canonical SDK contract for the installed version.

Error handling

All SDK errors derive from RevoError:

import {
  RevoError,
  RevoRemoteError,
  RevoTransportError,
} from '@revoengine/sdk';

try {
  await revo.api.insertDatabaseData('Sales', [{ saleId: 'sale-1' }]);
} catch (error) {
  if (error instanceof RevoTransportError && error.indeterminate) {
    // The request may have reached RevoEngine. Check by idempotency key or
    // business identifier before attempting the mutation again.
    throw error;
  }
  if (error instanceof RevoRemoteError) {
    console.error(error.code, error.statusCode, error.message);
    throw error;
  }
  if (error instanceof RevoError) {
    console.error(error.code, error.message);
    throw error;
  }
  throw error;
}

Common subclasses include:

  • RevoConfigurationError
  • RevoAuthenticationError
  • RevoPermissionDeniedError
  • RevoRuntimeContextUnavailableError
  • RevoBatchConfigurationError
  • RevoBatchLimitError
  • RevoRemoteError
  • RevoProtocolError
  • RevoTransportError

SDK compatibility notes

  • Node.js 22 or newer is required.
  • The package provides ESM, CommonJS, and TypeScript declarations.
  • The package has no runtime dependencies.
  • No package-level api, utils, storage, agents, or execute singleton is exported.
  • Deprecated low-code methods and aliases are excluded.
  • api.transactionDatabaseData is excluded.
  • Runtime batches are non-transactional and are not retried automatically.

Vault manager

The native client.vault manager uses the same get/create/update/delete/rotate contract for instance (default) and verified user scope. Get alone returns secret.revision.value as a Buffer containing the stored UTF-8 text; Rotate returns metadata without values. Revision versions are normalized validFrom timestamps. validFrom accepts null, Date, ISO or epoch milliseconds; a future Rotate preserves current availability. listRevisions exposes paginated metadata history.

const secret = await client.vault.get('TOKEN', { scope: 'user' });
const token = secret.revision.value.toString('utf8');
await client.vault.rotate('TOKEN', { value: replacement }, { scope: 'user', validFrom: null });

Do not log values or access tokens. Instance access requires Secret roles and creator ownership or administrator rights. User scope uses the verified account; management requires owner rights and does not inherit saved Component/Tool grants. Writes throw READ_ONLY_OPERATION_FORBIDDEN when the execution has readOnly: true. See the Vault guide for all methods.

The same flat manager exposes getAccessToken, getIntegrationMetadata, discoverIntegration, connectIntegration, and disconnectIntegration. Token reads return the access token with its matching ISO expiry and refresh when necessary. Connect requires nullable expectedRevision (null to create) and returns an authorization URL for interactive consent through the existing frontend callback. Disconnect retains definition/history/grants and does not revoke provider access. Saved Component/Tool reads preserve exact personal grants; direct SDK owner/admin reads and management are authorized separately.

Bulk Jobs and Webhooks

Use api.cancelJobs, retryJobs, deleteJobs, cancelWebhooks, retryWebhooks, and deleteWebhooks with exactly one non-empty platform filter or an ID array (jobIds / webhookIds, 1–1000 IDs). A filter selects every matching row beyond list pagination. An optional actor-scoped idempotencyKey protects repeat admission. The SDK never automatically retries mutations.

const input = {
  filter: { field: 'status', op: 'eq', value: 'ERROR' },
  idempotencyKey: 'retry-errors-2026-10-01',
};
const preview = await client.api.previewAutomationOperation('jobs', 'retry', input);
// Review advisory preview.matched / preview.eligible before submitting.
const operation = await client.api.retryJobs(input);
const progress = await client.api.getAutomationOperation(operation.operationId);
const outcomes = await client.api.getAutomationOperationItems(operation.operationId);
// Fetch subsequent pages with outcomes.nextCursor as the second argument.

Operations report PENDING, PROCESSING, FINISHED, or ERROR, plus total, processed, skipped, and failed. FINISHED means lifecycle requests were processed; downstream execution/delivery may continue and failed can be non-zero. Item pages contain safe source/result IDs and error codes. Preview is advisory; admission freezes selection and the worker rechecks state and permissions. Cancel/delete require Automation Admin; retry accepts Automation Runner/Admin.

retryWebhooks accepts requestPatch: url/method/body replace whole fields; headers/query accept set and remove, and maskDetails adds masks while preserving existing masks. Masked original values cannot be recovered: provide explicit replacements or the item fails with REPLAY_PAYLOAD_UNAVAILABLE. If the entire headers section was masked, headers.set supplies its complete replacement. Request patches are limited to 1 MiB of serialized JSON. Never log replacement credentials. The operation result does not expose saved request bodies.

await client.api.retryWebhooks({
  webhookIds: selectedWebhookIds,
  idempotencyKey: retryAdmissionKey,
  requestPatch: {
    headers: { set: { Authorization: `Bearer ${replacementToken}` }, remove: ['X-Old-Key'] },
    query: { set: { apiVersion: '2' }, remove: ['legacy'] },
    maskDetails: ['headers.Authorization'],
  },
});

The target platform requires the bulk-operation migration and an active API worker lane. Publishing this SDK does not deploy them or change the hosted SDK pin.