# TypeScript SDK

> The official TypeScript client — typed methods for every operation, cursor pagination, idempotency keys, retries and webhook verification.

Source: https://developers.processcart.com/guides/sdk

`@processcart/sdk` is the official TypeScript client for this API. It has one method per operation, named by the operation's `operationId` (the same name the [reference](https://developers.processcart.com/reference) shows), and its request and response types are typed from the [OpenAPI document](https://developers.processcart.com/guides/openapi). It also walks cursor pages, sends an `Idempotency-Key` on every write, retries what is safe to retry, and verifies webhook signatures.

## Install

```bash
npm install @processcart/sdk
```

The package is ESM with type declarations; it has no runtime dependencies.

## Create a client

```typescript
import { ProcessCart } from "@processcart/sdk";

const client = new ProcessCart({ apiKey: process.env.PROCESSCART_API_KEY! });
```

An Admin creates keys under **Settings → API** ([Authentication & API keys](https://developers.processcart.com/guides/authentication)). The client accepts a `pc_live_…` or `pc_test_…` key and refuses anything else before sending a request. A [sandbox](https://developers.processcart.com/guides/sandbox) uses the same base URL; the key decides which workspace you reach.

| Option      | Default                                                        | What it does                                                                     |
| ----------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `apiKey`    | —                                                              | Your API key (required).                                                         |
| `baseUrl`   | `https://app.processcart.com/api`                              | The server; paths add `/v1/…`. Change it only to reach a proxy or a test double. |
| `timeoutMs` | `30000`                                                        | The timeout of one attempt, in milliseconds.                                     |
| `retry`     | `{ maxAttempts: 3, maxDelayMs: 8000, retryAfterCapMs: 60000 }` | See [Retries](#retries).                                                         |
| `fetch`     | `globalThis.fetch`                                             | Any WHATWG-compatible `fetch`.                                                   |
| `userAgent` | `processcart-sdk/<version>`                                    | The `User-Agent` header.                                                         |

Every method also takes a last `options` argument for that one call: `idempotencyKey`, `expectedRevision`, `requestId` (sent as `X-Request-Id`), `signal` (an `AbortSignal`), `timeoutMs` and `retry`.

## Quickstart

The six steps of the [quickstart](https://developers.processcart.com), in TypeScript. The key needs the `runs:read`, `runs:write` and `workflows:read` scopes (or full access).

```typescript
// 1. Identify your key.
const me = await client.getMe();
console.log(`Connected to ${me.org.name} with the key "${me.key.name}"`);

// 2. Find a published workflow.
const workflows = await client.listWorkflows();
const workflow = workflows.data.find((w) => w.publishedVersion !== null);
if (!workflow) throw new Error("Publish a workflow first");

// 3. Start a run, with field values in the same transaction.
const run = await client.startRun({
  workflowId: workflow.id,
  name: "Order 1042",
  fields: { customer_email: "ada@example.com", amount: 1700.5 },
});

// 4. Set field values; refused with 409 if someone changed the run since you read it.
const updated = await client.setRunFields(
  run.id,
  { ship_date: "2026-10-09" },
  { expectedRevision: run.revision },
);

// 5. Complete the first open task.
const task = updated.tasks.find((t) => t.visible && !t.locked && t.state === "todo");
if (task) await client.completeTask(run.id, task.key, { expectedRevision: updated.revision });
```

Then the sixth step, hear about changes: every run updated since your last sync, across every page ([Incremental sync](https://developers.processcart.com/guides/incremental-sync)).

```typescript
for await (const changed of client.listRuns({ updatedSince: "2026-10-08T00:00:00Z" })) {
  console.log(changed.name, changed.revision);
}
```

A method resolves to the response body, so `run.tasks` and `run.fields` are typed. Path parameters come first, in path order, then the request body (or the query), then `options`.

## Pagination

A list method returns a request you can use three ways ([Pagination](https://developers.processcart.com/guides/pagination)):

```typescript
// The first page: { data, nextCursor, hasMore }.
const first = await client.listRuns({ limit: 50 });

// Every item across every page, following nextCursor with the same query.
for await (const run of client.listRuns({ status: ["active"] })) {
  console.log(run.name);
}

// Every page, each with its own $meta.
for await (const page of client.listRuns({ limit: 100 }).pages()) {
  console.log(page.data.length, page.$meta.requestId);
}
```

Nothing is sent until you `await` or iterate, and the iterator owns `cursor`. For [incremental sync](https://developers.processcart.com/guides/incremental-sync), walk `client.listRuns({ updatedSince })` from the instant of your last sync.

## Writes, idempotency and concurrency

Every `POST`, `PATCH` and `DELETE` carries an `Idempotency-Key`: a random UUID generated once per call and reused on each of that call's retries, so a retried call replays the stored answer instead of applying the change again ([Idempotency](https://developers.processcart.com/guides/idempotency)). Pass `options.idempotencyKey` to make a call safe to repeat across processes — derived from your own order number, say.

Every Run the API returns carries its `revision`. Send the one you last saw as `expectedRevision` (the client sends it as the `Expected-Revision` header) and a write that raced another one is refused with `409 revision_mismatch` instead of overwriting it ([Concurrency](https://developers.processcart.com/guides/concurrency)). Each write resolves to the updated run, so chain the next write from its `revision`:

```ts
const run = await client.getRun(runId);
const updated = await client.setRunFields(runId, { amount: 125 }, { expectedRevision: run.revision });
await client.completeTask(runId, "review", { expectedRevision: updated.revision });
```

`expectedRevision` takes the revision number (a non-negative integer; anything else throws a `TypeError` before a request is sent). On a `409 revision_mismatch` the error's `currentRevision` is the run's revision now: read the run again, merge, and retry with it. `deleteRunFile` answers `204`, so read the run before the next conditional write. Every method accepts the option, but only the writes that change an existing run read it: on schedules, automation rules, views, webhooks and workflows the server ignores it, and the last write wins. The API sends no `ETag` and refuses `If-Match` — CDN layers evaluate `If-Match` against the response and turn a successful write into a 412.

Every result also carries a non-enumerable `$meta` (`JSON.stringify` and deep-equality checks skip it):

| `$meta` field | What it holds                                                                  |
| ------------- | ------------------------------------------------------------------------------ |
| `status`      | The HTTP status.                                                               |
| `requestId`   | `X-Request-Id` — quote it to support.                                          |
| `revision`    | The run's revision, from the body (set on every Run read, create and write).   |
| `replayed`    | `true` when the API replayed the stored answer for the same `Idempotency-Key`. |
| `rateLimit`   | `{ limit, remaining, reset }` from the `RateLimit-*` headers.                  |
| `headers`     | The raw response headers.                                                      |

An operation that answers `204 No Content` (`deleteView`, `deleteWebhook`, `deleteRunFile`) resolves to an object holding only `$meta`.

## Retries
The client makes up to `maxAttempts` attempts in all, the first included (3 by default; `retry: { maxAttempts: 1 }` turns retries off). It retries:

- **429 `rate_limited`** — after `Retry-After` seconds, else after `RateLimit-Reset`, else with backoff ([Rate limits](https://developers.processcart.com/guides/rate-limits)).
- **409 `idempotency_in_progress`** — after `Retry-After`, or 2 seconds without one.
- **502, 503 and 504 on a `GET`** — after `Retry-After` when the response has one, else with backoff. A write that meets one is not retried (see below); the error carries `retryAfter`.
- **A network failure** (`fetch` itself threw) and **a timed-out attempt**.

A wait the server asked for is capped at `retryAfterCapMs` (60 seconds). Backoff waits 500 ms before the first retry and doubles each time, plus up to 250 ms of jitter, capped at `maxDelayMs` (8 seconds). It never retries a 500, a 502 / 503 / 504 on a write (a crash or a database outage after the commit can release the API's idempotency claim, so a retry with the same key could apply the change twice — re-running it is your call), any other 4xx, or a call you aborted with `signal`. When the attempts run out it throws the last failure. `getHealth` is the one call that resolves a 503: a degraded API answers `{ status: "degraded" }`, read `$meta.status` to tell it from a 200.

## Errors

Every API or transport failure rejects with a `ProcessCartError`; check for one with `isProcessCartError`:

```typescript
import { isProcessCartError } from "@processcart/sdk";

try {
  await client.completeTask(runId, "review");
} catch (error) {
  if (!isProcessCartError(error)) throw error;
  console.error(error.status, error.code, error.requestId);
  for (const e of error.errors ?? []) console.error(e.field, e.code, e.message);
}
```

The error carries `status` (`0` when no response arrived), `code` (an [error code](https://developers.processcart.com/errors), or `network_error`, `timeout` or `non_problem_response` from the client itself), `title`, `detail`, `requestId`, `errors` (the per-field problems of a 422), `retryAfter`, `headers`, the `problem` document as received, and `raw` (the response text when the body was not a problem document, such as a proxy's HTML page). On a `409 revision_mismatch`, `currentRevision` is the run's revision now (the problem body's `currentRevision`). A call you abort rejects with your abort reason, not a `ProcessCartError`. The code list is open: handle codes this version does not know.

## Files

`uploadRunFile` runs the three-step upload ([Files](https://developers.processcart.com/guides/tasks-approvals-files#files)) in one call: it requests an upload ticket, PUTs the bytes to the signed URL with exactly the ticket's headers and no API key, then finalizes.

```typescript
import { readFile } from "node:fs/promises";

const { attachment, run } = await client.uploadRunFile(runId, {
  target: { kind: "field", fieldKey: "packing_slip" },
  filename: "packing-slip.pdf",
  contentType: "application/pdf",
  bytes: await readFile("./packing-slip.pdf"),
});
```

`bytes` is a `Blob`, an `ArrayBuffer` or a `Uint8Array` (a Node `Buffer` is one); `size` defaults to its length. `options.expectedRevision` applies to the finalize step, and each API step gets its own `Idempotency-Key`. A refused PUT rejects with a `ProcessCartError` (`code: "non_problem_response"`, the storage answer in `raw`) and nothing is finalized.

## Webhooks

`@processcart/sdk/webhooks` verifies [Standard Webhooks](https://developers.processcart.com/webhooks) signatures with WebCrypto, without the client. Pass the RAW body — the exact bytes received, never a re-serialized object:

```typescript
import { createServer } from "node:http";
import { headersFromRequest, verifyWebhookSignature } from "@processcart/sdk/webhooks";
import type { WebhookEvent } from "@processcart/sdk/webhooks";

const secret = process.env.PROCESSCART_WEBHOOK_SECRET!; // whsec_…

createServer(async (req, res) => {
  const chunks: Buffer[] = [];
  for await (const chunk of req) chunks.push(chunk as Buffer);
  const body = Buffer.concat(chunks);
  const result = await verifyWebhookSignature(secret, headersFromRequest(req.headers), body);
  if (!result.ok) return void res.writeHead(400).end(result.reason);
  const event = JSON.parse(body.toString("utf8")) as WebhookEvent;
  res.writeHead(204).end(); // answer within 10 seconds, then do the work
  console.log(event.type, result.id); // dedupe on result.id
}).listen(3000);
```

With a `Request` (Workers, Deno, Bun, Next.js route handlers), read `await request.text()` and pass `headersFromRequest(request.headers)`. The check accepts any `v1` entry of `webhook-signature` (both secrets sign for 24 hours after a rotation) and refuses a `webhook-timestamp` more than 300 seconds from now (`toleranceSeconds` changes it). A failure resolves to `{ ok: false, reason }`: `missing_headers`, `bad_timestamp`, `timestamp_outside_tolerance`, `no_matching_signature` or `bad_secret`.

## Types

Every request and response type comes from the OpenAPI document, so the SDK types match what the API validates:

```typescript
import type { Run, RunTask, OpBody, OpQuery } from "@processcart/sdk";

type NewRun = OpBody<"startRun">; // the startRun body
type RunFilter = OpQuery<"listRuns">; // the listRuns query
```

The component schemas a method takes or returns are exported under their OpenAPI names (`Run`, `RunTask`, `RunField`, `WorkflowSummary`, `View`, `Webhook`, …); the raw `paths`, `components` and `webhooks` interfaces are exported too. `WebhookEvent` (from `@processcart/sdk/webhooks`) is the union of every event envelope, narrowed by `type`. Field values are typed per workflow at runtime — `getWorkflowSchema(id)` returns the JSON Schema of one workflow's run bodies ([Field values & typing](https://developers.processcart.com/guides/field-values)).

## Methods

| Method | HTTP | What it does |
| --- | --- | --- |
| [`getMe(…)`](https://developers.processcart.com/reference#tag/me/GET/v1/me) | <code class="pc-docs-wrap">GET /v1<wbr>/me</code> | Identify the API key and its workspace |
| [`getHealth(…)`](https://developers.processcart.com/reference#tag/health/GET/v1/health) | <code class="pc-docs-wrap">GET /v1<wbr>/health</code> | Check that the API is up |
| [`listRuns(…)`](https://developers.processcart.com/reference#tag/runs/GET/v1/runs) | <code class="pc-docs-wrap">GET /v1<wbr>/runs</code> | List runs |
| [`startRun(…)`](https://developers.processcart.com/reference#tag/runs/POST/v1/runs) | <code class="pc-docs-wrap">POST /v1<wbr>/runs</code> | Start a run |
| [`getRun(…)`](https://developers.processcart.com/reference#tag/runs/GET/v1/runs/{id}) | <code class="pc-docs-wrap">GET /v1<wbr>/runs<wbr>/{id}</code> | Get a run |
| [`updateRun(…)`](https://developers.processcart.com/reference#tag/runs/PATCH/v1/runs/{id}) | <code class="pc-docs-wrap">PATCH /v1<wbr>/runs<wbr>/{id}</code> | Update a run's name, priority, labels, due date or status |
| [`trashRun(…)`](https://developers.processcart.com/reference#tag/runs/DELETE/v1/runs/{id}) | <code class="pc-docs-wrap">DELETE /v1<wbr>/runs<wbr>/{id}</code> | Move a run to Trash |
| [`restoreRun(…)`](https://developers.processcart.com/reference#tag/runs/POST/v1/runs/{id}/restore) | <code class="pc-docs-wrap">POST /v1<wbr>/runs<wbr>/{id}<wbr>/restore</code> | Restore a run from Trash |
| [`listRunTasks(…)`](https://developers.processcart.com/reference#tag/tasks/GET/v1/runs/{id}/tasks) | <code class="pc-docs-wrap">GET /v1<wbr>/runs<wbr>/{id}<wbr>/tasks</code> | List a run's tasks |
| [`completeTask(…)`](https://developers.processcart.com/reference#tag/tasks/POST/v1/runs/{id}/tasks/{key}/complete) | <code class="pc-docs-wrap">POST /v1<wbr>/runs<wbr>/{id}<wbr>/tasks<wbr>/{key}<wbr>/complete</code> | Complete a task |
| [`reopenTask(…)`](https://developers.processcart.com/reference#tag/tasks/POST/v1/runs/{id}/tasks/{key}/reopen) | <code class="pc-docs-wrap">POST /v1<wbr>/runs<wbr>/{id}<wbr>/tasks<wbr>/{key}<wbr>/reopen</code> | Reopen a completed task |
| [`approveTask(…)`](https://developers.processcart.com/reference#tag/tasks/POST/v1/runs/{id}/tasks/{key}/approve) | <code class="pc-docs-wrap">POST /v1<wbr>/runs<wbr>/{id}<wbr>/tasks<wbr>/{key}<wbr>/approve</code> | Approve an approval task |
| [`rejectTask(…)`](https://developers.processcart.com/reference#tag/tasks/POST/v1/runs/{id}/tasks/{key}/reject) | <code class="pc-docs-wrap">POST /v1<wbr>/runs<wbr>/{id}<wbr>/tasks<wbr>/{key}<wbr>/reject</code> | Reject an approval task |
| [`setRunFields(…)`](https://developers.processcart.com/reference#tag/fields/PATCH/v1/runs/{id}/fields) | <code class="pc-docs-wrap">PATCH /v1<wbr>/runs<wbr>/{id}<wbr>/fields</code> | Set field values |
| [`listRunComments(…)`](https://developers.processcart.com/reference#tag/comments/GET/v1/runs/{id}/comments) | <code class="pc-docs-wrap">GET /v1<wbr>/runs<wbr>/{id}<wbr>/comments</code> | List a run's comments |
| [`createRunComment(…)`](https://developers.processcart.com/reference#tag/comments/POST/v1/runs/{id}/comments) | <code class="pc-docs-wrap">POST /v1<wbr>/runs<wbr>/{id}<wbr>/comments</code> | Comment on a task |
| [`getRunComment(…)`](https://developers.processcart.com/reference#tag/comments/GET/v1/runs/{id}/comments/{commentId}) | <code class="pc-docs-wrap">GET /v1<wbr>/runs<wbr>/{id}<wbr>/comments<wbr>/{commentId}</code> | Get a comment |
| [`requestRunFile(…)`](https://developers.processcart.com/reference#tag/files/POST/v1/runs/{id}/files) | <code class="pc-docs-wrap">POST /v1<wbr>/runs<wbr>/{id}<wbr>/files</code> | Request an upload ticket |
| [`finalizeRunFile(…)`](https://developers.processcart.com/reference#tag/files/POST/v1/runs/{id}/files/{attachmentId}/finalize) | <code class="pc-docs-wrap">POST /v1<wbr>/runs<wbr>/{id}<wbr>/files<wbr>/{attachmentId}<wbr>/finalize</code> | Finalize an upload |
| [`listRunFiles(…)`](https://developers.processcart.com/reference#tag/files/GET/v1/runs/{id}/files) | <code class="pc-docs-wrap">GET /v1<wbr>/runs<wbr>/{id}<wbr>/files</code> | List a run's files |
| [`getRunFile(…)`](https://developers.processcart.com/reference#tag/files/GET/v1/runs/{id}/files/{attachmentId}) | <code class="pc-docs-wrap">GET /v1<wbr>/runs<wbr>/{id}<wbr>/files<wbr>/{attachmentId}</code> | Get a file with a download link |
| [`deleteRunFile(…)`](https://developers.processcart.com/reference#tag/files/DELETE/v1/runs/{id}/files/{attachmentId}) | <code class="pc-docs-wrap">DELETE /v1<wbr>/runs<wbr>/{id}<wbr>/files<wbr>/{attachmentId}</code> | Remove a file |
| [`listRunActivity(…)`](https://developers.processcart.com/reference#tag/activity/GET/v1/runs/{id}/activity) | <code class="pc-docs-wrap">GET /v1<wbr>/runs<wbr>/{id}<wbr>/activity</code> | List a run's activity |
| [`listWorkflows(…)`](https://developers.processcart.com/reference#tag/workflows/GET/v1/workflows) | <code class="pc-docs-wrap">GET /v1<wbr>/workflows</code> | List workflows |
| [`createWorkflow(…)`](https://developers.processcart.com/reference#tag/workflows/POST/v1/workflows) | <code class="pc-docs-wrap">POST /v1<wbr>/workflows</code> | Create a workflow from a template |
| [`getWorkflow(…)`](https://developers.processcart.com/reference#tag/workflows/GET/v1/workflows/{id}) | <code class="pc-docs-wrap">GET /v1<wbr>/workflows<wbr>/{id}</code> | Get a workflow |
| [`updateWorkflow(…)`](https://developers.processcart.com/reference#tag/workflows/PATCH/v1/workflows/{id}) | <code class="pc-docs-wrap">PATCH /v1<wbr>/workflows<wbr>/{id}</code> | Update a workflow's name, description, folder, Key Date field or status |
| [`getWorkflowSchema(…)`](https://developers.processcart.com/reference#tag/workflows/GET/v1/workflows/{id}/schema) | <code class="pc-docs-wrap">GET /v1<wbr>/workflows<wbr>/{id}<wbr>/schema</code> | Get the JSON Schema for a workflow's run bodies |
| [`getWorkflowTemplate(…)`](https://developers.processcart.com/reference#tag/workflows/GET/v1/workflows/{id}/template) | <code class="pc-docs-wrap">GET /v1<wbr>/workflows<wbr>/{id}<wbr>/template</code> | Export a workflow as a portable template |
| [`listViews(…)`](https://developers.processcart.com/reference#tag/views/GET/v1/views) | <code class="pc-docs-wrap">GET /v1<wbr>/views</code> | List shared views |
| [`createView(…)`](https://developers.processcart.com/reference#tag/views/POST/v1/views) | <code class="pc-docs-wrap">POST /v1<wbr>/views</code> | Create a shared view |
| [`getView(…)`](https://developers.processcart.com/reference#tag/views/GET/v1/views/{id}) | <code class="pc-docs-wrap">GET /v1<wbr>/views<wbr>/{id}</code> | Get a shared view |
| [`updateView(…)`](https://developers.processcart.com/reference#tag/views/PATCH/v1/views/{id}) | <code class="pc-docs-wrap">PATCH /v1<wbr>/views<wbr>/{id}</code> | Update a shared view |
| [`deleteView(…)`](https://developers.processcart.com/reference#tag/views/DELETE/v1/views/{id}) | <code class="pc-docs-wrap">DELETE /v1<wbr>/views<wbr>/{id}</code> | Delete a shared view |
| [`listViewRuns(…)`](https://developers.processcart.com/reference#tag/views/GET/v1/views/{id}/runs) | <code class="pc-docs-wrap">GET /v1<wbr>/views<wbr>/{id}<wbr>/runs</code> | List the runs a view selects |
| [`listWebhooks(…)`](https://developers.processcart.com/reference#tag/webhooks/GET/v1/webhooks) | <code class="pc-docs-wrap">GET /v1<wbr>/webhooks</code> | List webhooks |
| [`createWebhook(…)`](https://developers.processcart.com/reference#tag/webhooks/POST/v1/webhooks) | <code class="pc-docs-wrap">POST /v1<wbr>/webhooks</code> | Create a webhook |
| [`getWebhook(…)`](https://developers.processcart.com/reference#tag/webhooks/GET/v1/webhooks/{id}) | <code class="pc-docs-wrap">GET /v1<wbr>/webhooks<wbr>/{id}</code> | Get a webhook |
| [`updateWebhook(…)`](https://developers.processcart.com/reference#tag/webhooks/PATCH/v1/webhooks/{id}) | <code class="pc-docs-wrap">PATCH /v1<wbr>/webhooks<wbr>/{id}</code> | Update a webhook |
| [`deleteWebhook(…)`](https://developers.processcart.com/reference#tag/webhooks/DELETE/v1/webhooks/{id}) | <code class="pc-docs-wrap">DELETE /v1<wbr>/webhooks<wbr>/{id}</code> | Delete a webhook |
| [`enableWebhook(…)`](https://developers.processcart.com/reference#tag/webhooks/POST/v1/webhooks/{id}/enable) | <code class="pc-docs-wrap">POST /v1<wbr>/webhooks<wbr>/{id}<wbr>/enable</code> | Enable a webhook |
| [`disableWebhook(…)`](https://developers.processcart.com/reference#tag/webhooks/POST/v1/webhooks/{id}/disable) | <code class="pc-docs-wrap">POST /v1<wbr>/webhooks<wbr>/{id}<wbr>/disable</code> | Disable a webhook |
| [`rotateWebhookSecret(…)`](https://developers.processcart.com/reference#tag/webhooks/POST/v1/webhooks/{id}/rotate-secret) | <code class="pc-docs-wrap">POST /v1<wbr>/webhooks<wbr>/{id}<wbr>/rotate-secret</code> | Rotate a webhook's signing secret |
| [`testWebhook(…)`](https://developers.processcart.com/reference#tag/webhooks/POST/v1/webhooks/{id}/test) | <code class="pc-docs-wrap">POST /v1<wbr>/webhooks<wbr>/{id}<wbr>/test</code> | Send a test event |
| [`listWebhookDeliveries(…)`](https://developers.processcart.com/reference#tag/webhooks/GET/v1/webhooks/{id}/deliveries) | <code class="pc-docs-wrap">GET /v1<wbr>/webhooks<wbr>/{id}<wbr>/deliveries</code> | List a webhook's deliveries |
| [`getWebhookDelivery(…)`](https://developers.processcart.com/reference#tag/webhooks/GET/v1/webhooks/{id}/deliveries/{deliveryId}) | <code class="pc-docs-wrap">GET /v1<wbr>/webhooks<wbr>/{id}<wbr>/deliveries<wbr>/{deliveryId}</code> | Get a delivery |
| [`redeliverWebhookDelivery(…)`](https://developers.processcart.com/reference#tag/webhooks/POST/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver) | <code class="pc-docs-wrap">POST /v1<wbr>/webhooks<wbr>/{id}<wbr>/deliveries<wbr>/{deliveryId}<wbr>/redeliver</code> | Send a delivery again |
| [`listSchedules(…)`](https://developers.processcart.com/reference#tag/schedules/GET/v1/schedules) | <code class="pc-docs-wrap">GET /v1<wbr>/schedules</code> | List schedules |
| [`createSchedule(…)`](https://developers.processcart.com/reference#tag/schedules/POST/v1/schedules) | <code class="pc-docs-wrap">POST /v1<wbr>/schedules</code> | Create a schedule |
| [`getSchedule(…)`](https://developers.processcart.com/reference#tag/schedules/GET/v1/schedules/{id}) | <code class="pc-docs-wrap">GET /v1<wbr>/schedules<wbr>/{id}</code> | Get a schedule |
| [`updateSchedule(…)`](https://developers.processcart.com/reference#tag/schedules/PATCH/v1/schedules/{id}) | <code class="pc-docs-wrap">PATCH /v1<wbr>/schedules<wbr>/{id}</code> | Update a schedule |
| [`deleteSchedule(…)`](https://developers.processcart.com/reference#tag/schedules/DELETE/v1/schedules/{id}) | <code class="pc-docs-wrap">DELETE /v1<wbr>/schedules<wbr>/{id}</code> | Delete a schedule |
| [`pauseSchedule(…)`](https://developers.processcart.com/reference#tag/schedules/POST/v1/schedules/{id}/pause) | <code class="pc-docs-wrap">POST /v1<wbr>/schedules<wbr>/{id}<wbr>/pause</code> | Pause a schedule |
| [`resumeSchedule(…)`](https://developers.processcart.com/reference#tag/schedules/POST/v1/schedules/{id}/resume) | <code class="pc-docs-wrap">POST /v1<wbr>/schedules<wbr>/{id}<wbr>/resume</code> | Resume a schedule |
| [`runScheduleNow(…)`](https://developers.processcart.com/reference#tag/schedules/POST/v1/schedules/{id}/run) | <code class="pc-docs-wrap">POST /v1<wbr>/schedules<wbr>/{id}<wbr>/run</code> | Start a run from a schedule now |
| [`previewSchedule(…)`](https://developers.processcart.com/reference#tag/schedules/GET/v1/schedules/{id}/preview) | <code class="pc-docs-wrap">GET /v1<wbr>/schedules<wbr>/{id}<wbr>/preview</code> | Preview a schedule's next occurrences |
| [`listAutomationRules(…)`](https://developers.processcart.com/reference#tag/automation-rules/GET/v1/automation-rules) | <code class="pc-docs-wrap">GET /v1<wbr>/automation-rules</code> | List automation rules |
| [`createAutomationRule(…)`](https://developers.processcart.com/reference#tag/automation-rules/POST/v1/automation-rules) | <code class="pc-docs-wrap">POST /v1<wbr>/automation-rules</code> | Create an automation rule |
| [`getAutomationRule(…)`](https://developers.processcart.com/reference#tag/automation-rules/GET/v1/automation-rules/{id}) | <code class="pc-docs-wrap">GET /v1<wbr>/automation-rules<wbr>/{id}</code> | Get an automation rule |
| [`updateAutomationRule(…)`](https://developers.processcart.com/reference#tag/automation-rules/PATCH/v1/automation-rules/{id}) | <code class="pc-docs-wrap">PATCH /v1<wbr>/automation-rules<wbr>/{id}</code> | Update an automation rule |
| [`deleteAutomationRule(…)`](https://developers.processcart.com/reference#tag/automation-rules/DELETE/v1/automation-rules/{id}) | <code class="pc-docs-wrap">DELETE /v1<wbr>/automation-rules<wbr>/{id}</code> | Delete an automation rule |
| [`enableAutomationRule(…)`](https://developers.processcart.com/reference#tag/automation-rules/POST/v1/automation-rules/{id}/enable) | <code class="pc-docs-wrap">POST /v1<wbr>/automation-rules<wbr>/{id}<wbr>/enable</code> | Turn an automation rule on |
| [`disableAutomationRule(…)`](https://developers.processcart.com/reference#tag/automation-rules/POST/v1/automation-rules/{id}/disable) | <code class="pc-docs-wrap">POST /v1<wbr>/automation-rules<wbr>/{id}<wbr>/disable</code> | Turn an automation rule off |
| [`listAutomationRuleExecutions(…)`](https://developers.processcart.com/reference#tag/automation-rules/GET/v1/automation-rules/{id}/executions) | <code class="pc-docs-wrap">GET /v1<wbr>/automation-rules<wbr>/{id}<wbr>/executions</code> | List a rule's executions |
| [`listUsers(…)`](https://developers.processcart.com/reference#tag/directory/GET/v1/users) | <code class="pc-docs-wrap">GET /v1<wbr>/users</code> | List members |
| [`listGroups(…)`](https://developers.processcart.com/reference#tag/directory/GET/v1/groups) | <code class="pc-docs-wrap">GET /v1<wbr>/groups</code> | List groups |
| [`exportRunsCsv(…)`](https://developers.processcart.com/reference#tag/exports/GET/v1/exports/runs.csv) | <code class="pc-docs-wrap">GET /v1<wbr>/exports<wbr>/runs.csv</code> | Export a workflow's runs as CSV |

`uploadRunFile(id, { target, filename, contentType, bytes, size? }, options?)` adds the one-call upload described under [Files](#files).

## Runtime support

The SDK needs `fetch` and WebCrypto: Node.js 22.12 or later, Deno, Bun and Cloudflare Workers. Use it from server-side code only — an API key acts on your whole workspace, so it never belongs in code that runs in a browser (the API sends no CORS headers).

## Versioning

The package follows semantic versioning, starting at 0.1.0; `SDK_VERSION` holds the installed version and rides the `User-Agent` header. It targets version 1 of the API (every path under `/v1`), which changes only additively ([Versioning & deprecation](https://developers.processcart.com/guides/versioning)).
