> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zapier.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> Release history for the Zapier TypeScript SDK and the Zapier SDK CLI

For usage details, see the [API Reference](/sdk/reference) and [CLI Reference](/sdk/cli-reference).

<Tabs>
  <Tab title="TypeScript SDK">
    ## 0.88.1 <a id="typescript-sdk-0-88-1" />

    * *This release contains no user-facing changes.*

    ## 0.88.0 <a id="typescript-sdk-0-88-0" />

    * Renamed time-duration options and parameters so every one carries its unit as a full-word suffix. Coarse durations (timeouts, waits, the retry-delay cap) now take **seconds**; genuinely sub-second knobs (poll cadence, the low-level `poll` primitive) take **milliseconds**. The old names still work but are deprecated — a caller passing a deprecated `*Ms` name keeps its millisecond meaning, so nothing changes silently; only the new names adopt the new unit.

      | Before                                                                      | After                                                     |
      | --------------------------------------------------------------------------- | --------------------------------------------------------- |
      | `createZapierSdk({ maxNetworkRetryDelayMs })`                               | `createZapierSdk({ maxNetworkRetryDelaySeconds })`        |
      | `createZapierSdk({ approvalTimeoutMs })`                                    | `createZapierSdk({ approvalTimeoutSeconds })`             |
      | `runAction({ timeoutMs })` (and `sdk.apps.<app>.<action>`)                  | `runAction({ timeoutSeconds })`                           |
      | `sdk.fetch(url, { maxTime })`                                               | `sdk.fetch(url, { maxTimeSeconds })`                      |
      | `createConnection` / `waitForNewConnection` `{ timeoutMs, pollIntervalMs }` | `{ timeoutSeconds, pollIntervalMilliseconds }`            |
      | `ApiClient.poll({ timeoutMs, initialDelay })`                               | `poll({ timeoutMilliseconds, initialDelayMilliseconds })` |
      | env `ZAPIER_MAX_NETWORK_RETRY_DELAY_MS`                                     | env `ZAPIER_MAX_NETWORK_RETRY_DELAY_SECONDS`              |

    ## 0.87.1 <a id="typescript-sdk-0-87-1" />

    * *This release contains no user-facing changes.*

    ## 0.87.0 <a id="typescript-sdk-0-87-0" />

    * Added brand-based type guards for recognizing SDK errors and signals without `instanceof`: `isZapierError`, per-subclass guards (`isZapierValidationError`, `isZapierApprovalError`, `isZapierNotFoundError`, `isZapierBundleError`, `isZapierTimeoutError`, and the rest), `isZapierSignal`, and the trigger-inbox signal guards `isZapierReleaseTriggerMessageSignal` and `isZapierAbortDrainSignal`.

      Prefer these over `instanceof` when handling SDK errors. `instanceof` compares class identity, which silently returns `false` when more than one copy of the SDK is loaded — for example a bundle that includes both the ESM and CommonJS builds, or a project that installs two versions. The guards match on a stable brand and the error `code`, so they keep working across those boundaries.

    ## 0.86.0 <a id="typescript-sdk-0-86-0" />

    * The experimental `publishWorkflowVersion` and `runDurable` methods can now have their `sourceFiles` map filled interactively, one file at a time (name, then contents), when resolved through the CLI or MCP. Calling the methods directly with a `sourceFiles` object is unchanged.

    ## 0.85.0 <a id="typescript-sdk-0-85-0" />

    * Paginated list results now expose `.pages()`, a plain async iterable over pages. Unlike iterating the result directly (which still works but is deprecated), `.pages()` is not also a promise, so returning it from an `async` function no longer silently collapses it to the first page. `.items()` is unchanged and remains the way to iterate individual items across pages. The `toIterable()` helper is deprecated in favor of `.pages()` and now logs a deprecation warning.

    ## 0.84.4 <a id="typescript-sdk-0-84-4" />

    * Added a `slug` field (e.g. `"google-sheets"`) to connection items returned by `getConnection`, `listConnections`, `findFirstConnection`, and `findUniqueConnection` (and their deprecated `listAuthentications` / `getAuthentication` / `findFirstAuthentication` / `findUniqueAuthentication` aliases).

    ## 0.84.3 <a id="typescript-sdk-0-84-3" />

    * Dynamic parameter pickers now resume from the pagination cursor on "Load more..." instead of re-fetching the first page. This fixes duplicate items and never-ending lists in the table picker and other paginated pickers. The table picker also notes when shared tables are hidden for the account (the connections picker already did), instead of silently showing fewer tables.

    ## 0.84.2 <a id="typescript-sdk-0-84-2" />

    * *This release contains no user-facing changes.*

    ## 0.84.1 <a id="typescript-sdk-0-84-1" />

    * Internal refactor of how item-returning methods produce their `{ data }` response envelope. No change to the SDK surface.

    ## 0.84.0 <a id="typescript-sdk-0-84-0" />

    * Code Substrate methods now use the `/code-substrate-runner` and `/code-substrate-workflows` API path prefixes across the SDK, the CLI, and the MCP server, and `sdk.context.api` and the CLI `curl` command accept paths built on them. The previous `/sdkdurableapi` and `/durableworkflowzaps` prefixes remain supported.

    ## 0.83.3 <a id="typescript-sdk-0-83-3" />

    * The app `version` field is now optional in `.zapierrc` manifest entries. A versionless entry resolves to the latest implementation at runtime. The CLI's `build-manifest` and `add` commands no longer error when an app has no version, writing a versionless entry instead.

    ## 0.83.2 <a id="typescript-sdk-0-83-2" />

    * This release contains no user-facing changes.

    ## 0.83.1 <a id="typescript-sdk-0-83-1" />

    * `getWorkflow` and `listWorkflows` now include a nullable `details` field on each trigger (e.g. `webhook_url` for catch-hook triggers). Also corrected the `trigger_url` field description to note that requests must also be authenticated as the account.

    ## 0.83.0 <a id="typescript-sdk-0-83-0" />

    * `createZapierSdk(options)` is unchanged in usage; the SDK is now built
      entirely on the module plugin system internally.

      * Deprecated SDK methods now log a runtime warning when called (once per
        process).
      * New: `disposeSdk(sdk)` releases the SDK's resources (telemetry timers,
        event listeners) — call it when you're done with an SDK in a long-lived
        process.
      * New for plugin authors: `zapierSdkPlugin` (the SDK's root plugin),
        `PluginSurface<typeof plugin>` (derive a plugin's surface type instead of
        hand-writing it), `resolvePlugin`, `declareOptionalProperty`,
        `SDK_OPTIONS_ID` / `sdkOptionsPluginRef`, explicit `MethodPlugin` /
        `PropertyPlugin` / `AggregatePlugin` descriptor types, the
        `PluginSummary` / `LeafSummary` ledger types and `EventTransport` (so a
        package exporting plugins can emit their inferred types in declarations),
        and `createController` with its `Controller*` types.

      Changed: `getConnection` now requires a connection locator — `connection`
      (or a deprecated `connectionId` / `authenticationId` alias) must be
      provided. It was previously optional in the type, with nothing sensible to
      fetch when omitted.

      Removed without a deprecation cycle (pre-1.0 break):

      * `createZapierSdkStack`, `createOptionsPlugin`, `createZapierCoreStack` —
        use `createZapierSdk(options)`, or compose module plugins with `createSdk`.
      * `dangerousContextPlugin` — import the specific plugin ref you need
        (`apiPluginRef`, `sdkOptionsPluginRef`, ...), or use `resolvePlugin` on a
        built sdk.
      * The `authenticationIdResolver` / `authenticationIdGenericResolver` aliases —
        use `connectionIdResolver` / `connectionIdGenericResolver`.

      Changed: the exported resolvers (`appKeyResolver`, `connectionIdResolver`,
      `inputsResolver`, ...) are now model resolvers — bag-form callbacks whose
      imports bind at build — instead of objects with `fetch(sdk, params)`
      callbacks. Attach them through a `defineMethod`'s `resolvers` map; they no
      longer work on a legacy function plugin's `meta.resolvers`.

    ## 0.82.1 <a id="typescript-sdk-0-82-1" />

    * `.zapierrc` manifest parsing now validates each entry independently, so a single malformed entry no longer discards the entire manifest. Previously one invalid `apps` entry caused the whole manifest, including a valid `connections` map, to be dropped, which could surface as a misleading "connection not found" error. Invalid entries are now dropped individually with a warning identifying the section and key.

    ## 0.82.0 <a id="typescript-sdk-0-82-0" />

    * Graduated Triggers and Trigger Inbox methods from the experimental interface to the stable one. Every trigger method (`listTriggers`, `listTriggerInputFields`, `createTriggerInbox`, `ensureTriggerInbox`, `drainTriggerInbox`, `watchTriggerInbox`, the inbox lifecycle methods, and the message lease/ack/release methods) is now available directly from `@zapier/zapier-sdk` and the `zapier-sdk` CLI — no `/experimental` import, `--experimental` flag, or `ZAPIER_EXPERIMENTAL` env var required. On the default MCP server the request/response trigger tools (`create-trigger-inbox`, `list-triggers`, the lease/ack/release tools, etc.) are now listed; the callback-driven `drainTriggerInbox` and `watchTriggerInbox` remain SDK/CLI-only. They stay available via the experimental subpath and `zapier-sdk-experimental` binary for backward compatibility.

    ## 0.81.1 <a id="typescript-sdk-0-81-1" />

    * Added `--callback-url` to `zapier-sdk login` and `zapier-sdk signup` for resuming pending non-interactive OAuth flows. Non-interactive login and signup now save pending state and exit immediately; run the same command later with `--callback-url <url>` to complete authentication from the browser callback URL.

      Login and signup telemetry now includes `used_non_interactive_mode` and `is_headless` on CLI command and auth lifecycle events.

    ## 0.81.0 <a id="typescript-sdk-0-81-0" />

    * Deprecated `name` in favor of `key` for trigger inboxes. `name` continues to work as a deprecated alias.
      * `createTriggerInbox` now accepts an optional `key` parameter; `name` is deprecated.
      * `ensureTriggerInbox` now takes `key` as its required idempotency identifier; passing `name` still works but is deprecated.
      * `listTriggerInboxes` now accepts a `key` filter; the `name` filter is deprecated.
      * Trigger inbox locators (the `inbox` argument on `getTriggerInbox`, `updateTriggerInbox`, and related methods) now resolve non-UUID values by `key`.
      * Trigger inbox responses now include a `key` field alongside `name` (both hold the same value; `key` may be `null` when an inbox has no natural key).

    ## 0.80.2 <a id="typescript-sdk-0-80-2" />

    * Decode JSON-string `input` on `triggerWorkflow` and `runDurable`. Their `input`
      field is freeform (`z.unknown()`), which the CLI surfaces as a raw string flag
      and never JSON-parses, so `--input '{"a":1}'` reached the API as a string and
      was double-encoded (server rejected it with `expected object, received string`).
      The input is now normalized at the schema boundary: a `{`/`[`-leading JSON
      string is decoded to its value, while objects and scalar strings pass through
      unchanged. This also fixes programmatic callers passing a JSON string.

    ## 0.80.1 <a id="typescript-sdk-0-80-1" />

    * *This release contains no user-facing changes.*

    ## 0.80.0 <a id="typescript-sdk-0-80-0" />

    * Add a resolution controller that completes a method's partial input into a fully validated one, prompting a host only when needed (`createController`), along with the `defineResolver` authoring API and cancellation signals (`CoreCancelledSignal`, `isCoreSignal`).

    ## 0.79.0 <a id="typescript-sdk-0-79-0" />

    * Display trusted SDK deprecation notices from Zapier API responses. The SDK sniffs `zapier-sdk-deprecation-*` response headers (never on relay responses), warns once per notice id per process — with no opt-out — and emits an `api:deprecation_notice` event for wrappers. The CLI additionally renders notices as a boxed stderr warning after command output, and the MCP server attaches them to every tool result so agents relay the warning to users.

    ## 0.78.0 <a id="typescript-sdk-0-78-0" />

    * Removed the deprecated `sdk.addPlugin(...)` chain method (and the `WithAddPlugin` type / chain-style no-arg `createSdk()` doorway). Extend a built SDK with the top-level `addPlugin(sdk, plugin)` instead.
    * `@zapier/zapier-sdk` now re-exports the plugin-authoring helpers (`createSdk`, `defineMethod` / `definePlugin` / `declareMethod` / etc., `selectExports`, `addPlugin`). Note `createSdk` reuses the old doorway's name but now takes a root plugin, so a stale no-arg `createSdk()` call is a compile error rather than silent misbehavior.

    ## 0.77.2 <a id="typescript-sdk-0-77-2" />

    * Fixed published type declarations that caused consumer TypeScript builds to fail with `Cannot find module` for a bundled-only dev dependency. Also fixed stray per-module declarations being published under `dist/src`.

    ## 0.77.1 <a id="typescript-sdk-0-77-1" />

    * *This release contains no user-facing changes.*

    ## 0.77.0 <a id="typescript-sdk-0-77-0" />

    * `triggerWorkflow` (and `trigger-workflow`) now authenticates with Zapier credentials and runs the workflow as the authenticated account; triggering is limited to workflows that account can access.

      Changed the `triggerWorkflow` response shape:

      | Before                       | After                                       |
      | ---------------------------- | ------------------------------------------- |
      | `{ workflow, status, body }` | `{ id, workflow_id, created_at }` on `data` |

      The call is unchanged: pass the workflow id and optional `input`.

    ## 0.76.2 <a id="typescript-sdk-0-76-2" />

    * *This release contains no user-facing changes.*

    ## 0.76.1 <a id="typescript-sdk-0-76-1" />

    * *This release contains no user-facing changes.*

    ## 0.76.0 <a id="typescript-sdk-0-76-0" />

    * The `./define` durable context types now match `@zapier/zapier-durable`: awaiting a callback created with `timeoutSeconds` is typed as resolving a `CallbackResult<T>` — `{ status: "delivered"; value; at }` or `{ status: "expired"; at }` — instead of the bare payload. The new `CallbackResult` and `CallbackOptionsWithTimeout` types are exported; `CallbackOptions` no longer carries `timeoutSeconds`, so deadline call sites type against `CallbackOptionsWithTimeout`.

    ## 0.75.0 <a id="typescript-sdk-0-75-0" />

    * `listWorkflowRuns` (and `list-workflow-runs`) no longer return `output` on list items. Workflow-run lists no longer carry the (potentially large, soon-externalized) run output; fetch a single run's output via `getWorkflowRun` / `get-workflow-run`. Use `status` (`finished`/`failed`) to know when output is available.

    ## 0.74.1 <a id="typescript-sdk-0-74-1" />

    * Surface trigger claim failure reason and workflow disable reason on the experimental `getWorkflow` / `listWorkflows` responses (and therefore the `get-workflow` / `list-workflows` CLI commands). Each `triggers[]` entry gains `error` (the latest claim's failure reason, present when `status` is `failed`), and the workflow gains a top-level `disabled_reason` (`trigger_claim_failed` when system-disabled, otherwise null). The two signals stay independent so an enabled workflow with a failed trigger is representable. Both fields are optional.

    ## 0.74.0 <a id="typescript-sdk-0-74-0" />

    * *This release contains no user-facing changes.*

    ## 0.73.1 <a id="typescript-sdk-0-73-1" />

    * CamelCase the input params on `runDurable` and `publishWorkflowVersion` (`sourceFiles`, `zapierDurableVersion`, `appVersions`, and the nested connection / app-version / trigger fields), keeping the old snake\_case names as deprecated aliases. Handlers map them back to the snake\_case wire body; output fields are unchanged.

    ## 0.73.0 <a id="typescript-sdk-0-73-0" />

    * *This release contains no user-facing changes.*

    ## 0.72.0 <a id="typescript-sdk-0-72-0" />

    * `listWorkflows` now paginates. `pageSize` (follows the SDK default page size; values above 100 are rejected) and `cursor` are honored in the SDK, and via the `list-workflows --page-size`/`--cursor` CLI flags that were previously no-ops. Iterating still returns all workflows; reading a single page now yields at most `pageSize` results rather than the full list.

    ## 0.71.1 <a id="typescript-sdk-0-71-1" />

    * Rename `createWorkflow`'s `is_private` input to `private` to match `runDurable`, keeping `is_private` as a deprecated alias; the wire field stays `is_private`. Clarify the `run-durable` connections param description to show the required object shape.

    ## 0.71.0 <a id="typescript-sdk-0-71-0" />

    * Add `createConnection` and two lower-level building blocks for connecting an app from code, end to end:

      * `createConnection({ app, browser?, timeoutMs?, pollIntervalMs? })` — high-level: mints a connection URL, prints it (and opens it in a browser when it's safe to do so), waits for the user to finish, and returns the new connection. `browser` is `"auto"` (default — opens locally, skips CI / SSH / headless Linux), `"always"`, or `"never"`. The URL is always printed, so a skipped or failed open falls back to copy/paste.
      * `getConnectionStartUrl({ app })` — low-level: mints a short-lived, signed start URL bound to the current user/account. Returns `{ url, startedAt, expiresAt, app }`.
      * `waitForNewConnection({ app, startedAt, timeoutMs?, pollIntervalMs? })` — low-level: polls until a connection for the app created at or after `startedAt` appears, then returns `{ id, app, title? }`. Throws `ZapierTimeoutError` after `timeoutMs` (default 5 minutes).

      `createConnection` is the right call for most cases. Reach for the two low-level methods when you want to hand off the URL without blocking (call `getConnectionStartUrl` alone), or do something custom between minting the URL and waiting — email it, post it to Slack, render a QR code — then call `waitForNewConnection`.
    * Add private-beta support for streaming auto-mode approval review messages and handling terminal failed approvals through the SDK and CLI. Auto mode is only enabled service-side for approved beta users.

    ## 0.70.4 <a id="typescript-sdk-0-70-4" />

    * Response-field additions to experimental workflow and durable-run methods:
      * `updateWorkflow`, `getWorkflow`, `listWorkflows` responses now include `is_private`, `created_by_user_id`, and (where applicable) `triggers` with live claim status.
      * `publishWorkflowVersion`, `getWorkflowVersion`, `listWorkflowVersions` responses now include `trigger`, `connections`, and `app_versions`.
      * `runDurable` input accepts `notifications` (webhook subscribers for run lifecycle events).

    ## 0.70.3 <a id="typescript-sdk-0-70-3" />

    * `getDurableRun` no longer throws when `last_error` is `null` on a successful run.

    ## 0.70.2 <a id="typescript-sdk-0-70-2" />

    * `listActions` now includes private and unlisted apps the caller can access; results remain access-scoped server-side.

    ## 0.70.1 <a id="typescript-sdk-0-70-1" />

    * Workflow and durable-run responses no longer throw a parse error when the server returns unrecognized enum values.

    ## 0.70.0 <a id="typescript-sdk-0-70-0" />

    * `watchTriggerInbox` now retries transient drain failures (5xx, 429,
      network blips) indefinitely with bounded backoff instead of rejecting
      on the first error; it still rejects immediately on fail-fast handler
      errors, `initialization_failure`, and permanent HTTP errors. When those
      retries persist long enough to saturate the backoff, it warns once on
      stderr (re-armed on recovery) so a stalled watch isn't silent.

      New `ApiClient.fetchJsonStream` (with the `JsonSseMessage` type): like
      `fetchStream` but JSON-parses each frame, surfacing a malformed frame
      as `{ parsed: false, data: null, raw }` instead of throwing, so one
      bad frame can't kill a long-lived stream. A non-ok response still
      throws the shared `ZapierError` subclasses before the first frame.

      Fixed: a fail-fast handler that throws a falsy value (`throw
      undefined`) is no longer silently swallowed, and a handler-thrown
      AbortError now rejects the watch instead of resolving it cleanly.

    ## 0.69.3 <a id="typescript-sdk-0-69-3" />

    * Restored `connections`, `app_versions`, and `trigger` input fields on `publishWorkflowVersion` (experimental) that were unintentionally dropped in a prior release, leaving workflows unable to bind connection aliases or wire a trigger. Shape: connections as `{alias: {connection_id: ...}}`, app\_versions as `{alias: {implementation_name, version?}}`, trigger as a nested object with `selected_api` + `action` required.

    ## 0.69.2 <a id="typescript-sdk-0-69-2" />

    * Fixed logout so it reliably clears local authentication state even when the server cannot revoke the credential. Previously a failed revocation could abort logout and strand the user with credentials they could not remove. Re-login flows are unaffected; they still surface revocation failures before replacing credentials.

    ## 0.69.1 <a id="typescript-sdk-0-69-1" />

    * Fix paginated list results silently truncating to page 1 when the same result is consumed twice (iterating pages then `.items()`, `.items()` then pages, or iterating either one twice). Pages and items are now two views over one page stream, so consuming either drains the other: the second view yields nothing instead of silently replaying page 1. A paginated result is consumed once; call the method again for a fresh result. Awaiting the result to read just the first page is unaffected: it is a repeatable peek that does not start the stream, so awaiting and then iterating still works.

    ## 0.69.0 <a id="typescript-sdk-0-69-0" />

    * Switched `watchTriggerInbox` from backoff polling to a Server-Sent Events subscription, so it now wakes on near-real-time inbox notifications instead of repeatedly polling for new messages.
      * The `maxDrainIntervalSeconds` option now controls a periodic safety drain that backstops the SSE stream — guaranteeing forward progress if events are missed or the connection drops — and its default changed from 60 to 300 seconds.
      * Real-time wake-up health is now reported on stderr: a warning when wake-ups pause and the watch falls back to the safety drain, plus transient reconnect notices in debug mode. stdout (including `--json` NDJSON output) is unaffected.
      * Added a `fetchStream` method to the API client, along with an exported `SseMessage` type, for opening Server-Sent Events connections through the standard request pipeline (auth, base URL, 429 retry, approval, and concurrency).

    ## 0.68.1 <a id="typescript-sdk-0-68-1" />

    * *This release contains no user-facing changes.*

    ## 0.68.0 <a id="typescript-sdk-0-68-0" />

    * Added `zapier-sdk signup` for browser-based account setup and local SDK credential provisioning.

    ## 0.67.0 <a id="typescript-sdk-0-67-0" />

    * New stack-based composition surface for building on top of the SDK:
      `createZapierSdkStack(options)` (from the root and `/experimental`) returns
      the unsealed `PluginStack` that `createZapierSdk` materializes, and
      `createPluginStack`, `createCorePlugin`, and `addPlugin` are re-exported from
      the root. Build by chaining `.use(...)` and sealing with `.toSdk()`, or
      extend a sealed SDK in place with `addPlugin(sdk, plugin)`. The chain-style
      `createSdk().addPlugin(...)` pattern is deprecated (now logs a one-time
      warning) but still works.

      One behavior change: `normalizeError` no longer wraps thrown `Error` subclasses,
      so a handler's `TypeError` or a userland `MyAppError` bubbles through unchanged
      and `instanceof` works again; only non-`Error` throws get wrapped.
    * Route all debug, diagnostic, and telemetry log output to stderr (`console.error`) instead of stdout (`console.log`) across the SDK and CLI packages. The CLI now reserves stdout exclusively for the program's data payload — command output, JSON envelopes, response bodies — so callers can safely pipe CLI output through `jq`, `> redirect`, or `JSON.parse` even when `--debug` is on or telemetry/logging flags are enabled. Interactive terminal users see no change since both streams interleave in a TTY.

    ## 0.66.0 <a id="typescript-sdk-0-66-0" />

    * Added `triggerWorkflow` (experimental) to fire a workflow's trigger with a user-supplied JSON payload. Only available via `@zapier/zapier-sdk/experimental`. The workflow id is UUID-validated at the input boundary; trigger endpoint failures (non-2xx, or workflow with no published version) surface as descriptive errors.
    * Limit approval polling waits to at most 5 seconds while preserving the existing generic polling cadence.
    * Route `--debug` log output to stderr (`console.error`) instead of stdout (`console.log`) in `auth.ts` and `api/debug.ts`. This restores stdout's Unix contract — stdout carries only the program's data payload — so callers can safely pipe CLI output through `jq`, redirect to a file, or `JSON.parse` it even when `--debug` is on. Debug output still appears in CI logs and developer terminals (both streams interleave there).

    ## 0.65.0 <a id="typescript-sdk-0-65-0" />

    * Added `listWorkflowRuns`, `getWorkflowRun`, and `getTriggerRun` (experimental). All three live behind `@zapier/zapier-sdk/experimental` only — the stable subpath does not surface them. `listWorkflowRuns` is paginated; `getWorkflowRun` looks up a run by id; `getTriggerRun` walks from a trigger id to its associated run, useful immediately after firing a trigger when the caller has the trigger id but not yet the run id. All ID inputs are UUID-validated at the schema boundary. Consumers see any richer fields the server adds without an SDK release.

    ## 0.64.0 <a id="typescript-sdk-0-64-0" />

    * Added `publishWorkflowVersion`, `listWorkflowVersions`, and `getWorkflowVersion` (experimental). All three are registered only in `@zapier/zapier-sdk/experimental`; the stable subpath does not expose them. `listWorkflowVersions` is paginated (cursor + pageSize); `publishWorkflowVersion` takes `source_files` (filename → contents) plus optional `dependencies`, `zapier_durable_version`, and `enabled` (defaults to true); `getWorkflowVersion` returns the full version state including source files. Callers see any richer fields the server adds later without an SDK release. All ID inputs are UUID-validated so non-UUID strings fail with a clear schema error.

    ## 0.63.0 <a id="typescript-sdk-0-63-0" />

    * Added `runDurable` and `cancelDurableRun` (experimental). Both are registered only in `@zapier/zapier-sdk/experimental`; the stable subpath does not expose them. `runDurable` takes `source_files` (filename → contents) plus optional `input`/`dependencies`/`zapier_durable_version`/`connections`/`app_versions`, and a `private` flag; returns the run ID immediately in `initialized` status — callers that need terminal status poll via `getDurableRun`; no built-in polling. `cancelDurableRun` returns `{ id, status: "cancelled" }` on success, and propagates `ZapierNotFoundError` (404) and `ZapierConflictError` (409 — run already terminal) so callers can distinguish those outcomes.

    ## 0.62.0 <a id="typescript-sdk-0-62-0" />

    * Added `listDurableRuns` and `getDurableRun` (experimental). Both are registered only in `@zapier/zapier-sdk/experimental`; the stable subpath does not expose them. `listDurableRuns` is paginated (cursor + pageSize); `getDurableRun` returns the full run state with nested execution and operations journal. Callers see any richer fields the server adds later without an SDK release. The run id input is UUID-validated so non-UUID strings fail with a clear schema error.

    ## 0.61.0 <a id="typescript-sdk-0-61-0" />

    * Added `createWorkflow`, `updateWorkflow`, `enableWorkflow`, `disableWorkflow`, and `deleteWorkflow` (experimental). All five are registered only in `@zapier/zapier-sdk/experimental`; the stable subpath does not expose them. `deleteWorkflow` requires explicit confirmation before the destructive call. The workflow id input is UUID-validated so non-UUID strings fail with a clear schema error. Callers see any richer fields the server adds later without an SDK release.
    * Fix login/logout reliability bugs.

      **Bug fixes:**

      * `logout` now warns and still clears local keychain/registry state when the server returns 401 during revocation (404 is still silently swallowed; 401 is surfaced as a console warning so users know to verify or revoke the credential manually if needed)
      * Re-login no longer fails with "already exists" when a locally-orphaned registry entry has the same name as the desired new credential
      * `logout` no longer prompts for confirmation before deleting credentials; it always proceeds immediately, which also fixes hangs in non-TTY/CI environments

      **Deprecations:**

      * `--skip-prompts` on `login` and `init` is deprecated in favour of `--non-interactive`. The old flag continues to work with a deprecation warning.

    ## 0.60.0 <a id="typescript-sdk-0-60-0" />

    * Added `listWorkflows` and `getWorkflow` (experimental). Both are registered only in `@zapier/zapier-sdk/experimental`; the stable subpath does not expose them. `listWorkflows` is paginated with `pageSize`/`cursor`/`maxItems` options so callers can iterate via `for await (const page of sdk.listWorkflows())` or `toIterable(sdk.listWorkflows())`.

    ## 0.59.0 <a id="typescript-sdk-0-59-0" />

    * *This release contains no user-facing changes.*

    ## 0.58.0 <a id="typescript-sdk-0-58-0" />

    * Export `eventEmissionPlugin` (and its config/cleanup helpers) from the package root so consumers can compose their own SDK with `createSdk`. The plugin's existing helpers and types are now exposed via the plugin module itself instead of being re-listed in the SDK index.

    ## 0.57.0 <a id="typescript-sdk-0-57-0" />

    * Added a `trash` option to `listTableRecords` and `listTableFields` for controlling soft-deleted item visibility. Accepts `"exclude"` (default, active items only), `"include"` (active and soft-deleted), or `"only"` (soft-deleted items only).

    ## 0.56.2 <a id="typescript-sdk-0-56-2" />

    * *This release contains no user-facing changes.*

    ## 0.56.1 <a id="typescript-sdk-0-56-1" />

    * Clarified the `releaseOnError` option description for `drainTriggerInbox` and `consumeTriggerInbox`: errors release the message when the drain finishes, not immediately.

    ## 0.56.0 <a id="typescript-sdk-0-56-0" />

    * Allow opting into approvals during login

    ## 0.55.0 <a id="typescript-sdk-0-55-0" />

    * Add `hint?: string | string[]` to `PromptConfig.choices`. The CLI renders it after the choice's `name` as dimmed parens; an unset `hint` with a primitive `value` auto-renders the value.

      All built-in resolvers migrate to the new shape, so existing dropdowns get small visual cleanups (dim parens, no `ID:` prefix, dash converted to parens, em-dash in `tableRecordId` gone).

      Plugin authors who embed the value in `name` (e.g. `"Foo (${id})"`) should drop the embedded parens; the auto-default appends a second otherwise.

    ## 0.54.1 <a id="typescript-sdk-0-54-1" />

    * Add optional `name` parameter to `createTriggerInbox` method

    ## 0.54.0 <a id="typescript-sdk-0-54-0" />

    * Add type-to-filter to interactive single-select dropdowns: dynamic resolvers (apps, connections, tables, table records, etc.) and SELECT-format field choices. `(Load more...)` remains reachable even when a search yields zero matches, so users can pull the next page and try again.

      Dynamic resolvers also gain an `inputType: "search"` mode: the CLI prompts for free-form text, hands it to `fetch` as `search`, and either short-circuits on a primitive return (exact match) or renders results as a search-filterable dropdown. Empty results expose `(Use "foo" as-is)` and `(Try a different search)` so a required parameter can never strand the user. The built-in `appKey` resolver now uses this mode (`getApp` for exact match, `listApps --search` for fallback).

      `DynamicResolver` is now a discriminated union of `DynamicListResolver` and `DynamicSearchResolver`. Note for plugin authors: the `placeholder` field is now typed as `never` on the list variant, so a classic list resolver that was previously setting an unused `placeholder` will see a TypeScript error. Move it into a search-mode variant (`inputType: "search"`) or drop it — the CLI never read it on list resolvers.

    ## 0.53.0 <a id="typescript-sdk-0-53-0" />

    * Trigger inbox fixes and additions:
      * Send `connection_id: null` for trigger inboxes without a connection so connection-less apps (e.g. tables) work correctly.
      * Add `listTriggers`, a read variant of `listActions` that lists an app's triggers.
      * Add interactive resolvers to trigger inbox message methods: `ackTriggerInboxMessages` and `releaseTriggerInboxMessages` prompt for `messages` with a multi-select of leased messages; `leaseTriggerInboxMessages` prompts for `leaseLimit` and `leaseSeconds`.
      * CLI: coerce static prompt input to the schema's underlying type so numeric/boolean fields (e.g. `leaseLimit`, `leaseSeconds`) no longer fail Zod validation with "expected number, received string".

    ## 0.52.0 <a id="typescript-sdk-0-52-0" />

    * Add a configurable concurrency limit so the SDK queues requests beyond `maxConcurrentRequests` (FIFO) instead of firing them all at once. Default is 200. Configurable via the `createZapierSdk({ maxConcurrentRequests })` option or the `ZAPIER_MAX_CONCURRENT_REQUESTS` env var (the option wins). Pass `Infinity` to disable. Slots are held across 429 retries (so server backoff isn't undermined by extra parallelism) but released as soon as response headers arrive — streaming responses (SSE, long-running chunked reads) do not pin a permit for the lifetime of the body. Queued acquires respect `AbortSignal`. Queued requests emit `api:concurrency_wait_start` / `api:concurrency_wait_end` events for diagnostics.

    ## 0.51.0 <a id="typescript-sdk-0-51-0" />

    * Default SDK auth to client credentials
    * Updated the experimental Triggers notice in all three package READMEs to clarify that the feature is in closed beta, with a link to contact us for access.

    ## 0.50.0 <a id="typescript-sdk-0-50-0" />

    * Collapse the approval-flow surface into a single tri-state `approvalMode` option.

      What changed:

      * `approvalMode` is now `"disabled" | "poll" | "throw"` (was `"poll" | "fail"`).
      * `"disabled"` is the default. While the approval flow is alpha, callers must opt in explicitly via `approvalMode: "poll"` or `approvalMode: "throw"` (or the `ZAPIER_APPROVAL_MODE` env var). On an approval-required response, `"disabled"` throws a `ZapierApprovalError` with `status: "approval_required"` without creating an approval.
      * The `isInteractive` SDK option and the `ZAPIER_IS_INTERACTIVE` env var have been removed. Their role is subsumed by `approvalMode`: choosing `"poll"` / `"throw"` is the explicit opt-in that previously required `isInteractive: true`.
      * `"fail"` has been renamed to `"throw"` (both the option value and the `ZAPIER_APPROVAL_MODE` env var value). The behavior is unchanged: throw a `ZapierApprovalError` carrying the approval URL so the caller can surface it.
      * `approvalMode`, `approvalTimeoutMs`, and `maxApprovalRetries` are now part of the public API (no longer marked `internal: true`).

      There is no back-compat shim. `approvalMode: "fail"` and `isInteractive: <anything>` will fail Zod validation up front.

    ## 0.49.0 <a id="typescript-sdk-0-49-0" />

    * Add experimental support for triggers.

    ## 0.48.1 <a id="typescript-sdk-0-48-1" />

    * *This release contains no user-facing changes.*

    ## 0.48.0 <a id="typescript-sdk-0-48-0" />

    * Adds an extension mechanism that lets the CLI and MCP server load additional plugin packages at runtime. Set `ZAPIER_SDK_EXTENSIONS` to a comma-separated list of package specifiers, or pass them via the new `extensions` option — methods they contribute show up automatically as CLI commands and MCP tools, no per-project wiring required.

      When a plugin tries to register a method, context field, or meta entry that's already registered by another plugin in the chain, `addPlugin` now logs a warning and skips the duplicate plugin's contribution rather than silently overwriting. This catches the common foot-gun of an extension accidentally shadowing a built-in SDK method. Intentional duplicates can be expressed via `composePlugins(...)`, and meta-only overrides (e.g. tagging a built-in method as deprecated) continue to work unchanged.

    ## 0.47.1 <a id="typescript-sdk-0-47-1" />

    * The approval `poll_url` and `approval_url` origin checks are now skipped when `baseUrl` (or `ZAPIER_BASE_URL`) points at `localhost` / `127.0.0.1`, so local development works without origin validation errors.

    ## 0.47.0 <a id="typescript-sdk-0-47-0" />

    * Add `composePlugins(...subPlugins)` for bundling N plugins into a single `Plugin<TSdk, TProvides>` so a consumer can call `addPlugin(combined)` once. Bag-mode composition: throws on duplicate root keys or duplicate `context.meta` keys, intersects each sub-plugin's TSdk requirements, and flows through the existing single-plugin `addPlugin` without the type-widening an array overload would impose.

    ## 0.46.2 <a id="typescript-sdk-0-46-2" />

    * *This release contains no user-facing changes.*

    ## 0.46.1 <a id="typescript-sdk-0-46-1" />

    * Removed custom error handlers and added definePlugin, createPluginMethod, and createPaginatedPluginMethod to reduce plugin boilerplate.

    ## 0.46.0 <a id="typescript-sdk-0-46-0" />

    * Rename the client credentials persistence seam from storage to cache and expose the CLI filesystem/keychain adapter as a best-effort cache.

    ## 0.45.2 <a id="typescript-sdk-0-45-2" />

    * Convert API query params from camelCase to snake\_case (`appKeys` → `app_keys`, `pageSize` → `page_size`) to match the updated API contract.

    ## 0.45.1 <a id="typescript-sdk-0-45-1" />

    * *This release contains no user-facing changes.*

    ## 0.45.0 <a id="typescript-sdk-0-45-0" />

    * `registryPlugin` is now deprecated, because `getRegistry` is built into the SDK and added after each plugin is added. Plugins will always be registered; there is no need to call `createZapierSdkWithoutRegistry`, add custom plugins, and then `.addPlugin(registryPlugin)`. Because of this, `createZapierSdkWithoutRegistry` is now deprecated, and calling it will still give you an SDK with `getRegistry` on it. Calling `addPlugin(registryPlugin)` on that SDK is a no-op.

    ## 0.44.0 <a id="typescript-sdk-0-44-0" />

    * Allow UUID connection IDs in the `.zapierrc` connections map. `ConnectionEntrySchema.connectionId` now accepts either a positive integer (legacy form) or a UUID-format string (returned by the Zapier connections API for newer connections).

    ## 0.43.0 <a id="typescript-sdk-0-43-0" />

    * Add an experimental interactive approval flow for policy-gated actions. When an action requires approval, the SDK detects the `approval_required` response, prompts for approval in interactive sessions, and automatically retries the original request once approved. Non-interactive sessions receive a clear error explaining that approval is required. This flow is experimental and its behavior may change in future releases.

    ## 0.42.1 <a id="typescript-sdk-0-42-1" />

    * Simplify plugin system: plugins now receive sdk as a positional parameter with context at sdk.context. The Plugin type takes 2 generics (input SDK shape, output provides) instead of 3. Context is shallow-frozen to prevent reassignment of top-level properties. createSdk() is now zero-arg; SDK options are injected via createOptionsPlugin(options) through addPlugin like any other state. Plugins that need options declare it as an explicit context dependency. The addPluginOptions second argument to addPlugin has been removed.

    ## 0.42.0 <a id="typescript-sdk-0-42-0" />

    * Support maxTime for SDK fetch & CLI curl - Relay extended timeout

    ## 0.41.2 <a id="typescript-sdk-0-41-2" />

    * Fix connection resolution for no-auth apps

    ## 0.41.1 <a id="typescript-sdk-0-41-1" />

    * `formatErrorMessage` now renders `ZapierRateLimitError` details (limit used, time until retry, retry count) instead of just the bare "Rate limited" message. CLI, MCP, and any consumer using `formatErrorMessage` now surface which rate-limit window tripped and how long until it resets.

    ## 0.41.0 <a id="typescript-sdk-0-41-0" />

    * Prefer public IDs over numeric IDs in responses

    ## 0.40.4 <a id="typescript-sdk-0-40-4" />

    * Replace Node-only imports (timers/promises, os) with browser-safe alternatives and add browser compatibility test suite

    ## 0.40.3 <a id="typescript-sdk-0-40-3" />

    * Connections - Replace isExpired with expired

    ## 0.40.2 <a id="typescript-sdk-0-40-2" />

    * Make sure CLI only shows non-deprecated positional parameters.

    ## 0.40.1 <a id="typescript-sdk-0-40-1" />

    Several **top-level method options** were renamed so flexible resource references use **suffix-less** names (`app` instead of `appKey`, `connection` instead of `connectionId`, and so on). The values you pass are the same as before—slugs, implementation keys, versioned IDs, connection aliases, numeric IDs, and other supported forms. The goal is one obvious parameter per resource and less ambiguity between `*Key` and `*Id` now that parameters like `connection` already accept multiple identifier styles.

    **Note:** This is **not a breaking change**. The old parameter names still work; they are **deprecated**.

    | Old name        | New name      |
    | --------------- | ------------- |
    | `appKey`        | `app`         |
    | `appKeys`       | `apps`        |
    | `actionKey`     | `action`      |
    | `inputFieldKey` | `inputField`  |
    | `connectionId`  | `connection`  |
    | `connectionIds` | `connections` |
    | `tableId`       | `table`       |
    | `tableIds`      | `tables`      |
    | `recordId`      | `record`      |
    | `recordIds`     | `records`     |
    | `fieldKeys`     | `fields`      |
    | `accountId`     | `account`     |
  </Tab>

  <Tab title="CLI">
    ## 0.67.1 <a id="cli-0-67-1" />

    * *This release contains no user-facing changes.*

    ## 0.67.0 <a id="cli-0-67-0" />

    * Renamed time-duration flags and env vars so every one carries its unit as a full-word suffix. Coarse durations move to **seconds**; the deprecated names still work (and keep their millisecond meaning).
      * `--max-network-retry-delay-ms` → `--max-network-retry-delay-seconds`
      * `run-action --timeout-ms` → `--timeout-seconds`
      * `create-connection` / `wait-for-new-connection` `--timeout-ms` → `--timeout-seconds`, `--poll-interval-ms` → `--poll-interval-milliseconds`
      * env `ZAPIER_SDK_UPDATE_CHECK_INTERVAL_MS` → `ZAPIER_SDK_UPDATE_CHECK_INTERVAL_SECONDS`

    ## 0.66.5 <a id="cli-0-66-5" />

    * *This release contains no user-facing changes.*

    ## 0.66.4 <a id="cli-0-66-4" />

    * The CLI now reports the correct error code and enriched message for SDK errors. Previously some errors surfaced as `UNKNOWN_ERROR` with an unformatted message (and lost their code in `--json` output) because an `instanceof` check failed across the CLI's bundled copies of the SDK.

    ## 0.66.3 <a id="cli-0-66-3" />

    * A command whose parameters come only from its input schema (no declared resolvers) now prompts for a missing required parameter instead of erroring; `publish-workflow-version` is the one such command today. Non-interactively, missing required parameters are still reported together. Typed object, array, and record answers now accept JSON.

    ## 0.66.2 <a id="cli-0-66-2" />

    * Updated a debug hint in the legacy parameter resolver to point at the paginated result's `.pages()` instead of the deprecated `toIterable()` helper.

    ## 0.66.1 <a id="cli-0-66-1" />

    * `list-connections`, `get-connection`, `find-first-connection`, and `find-unique-connection` (and their deprecated `list-authentications` / `get-authentication` / `find-first-authentication` / `find-unique-authentication` aliases) now show the connected app's key and slug in their output.

    ## 0.66.0 <a id="cli-0-66-0" />

    * Interactive parameter pickers keep your place across "Load more…": earlier options stay on the list in order above the cursor, the cursor lands on the first newly loaded option, and type-to-filter covers everything loaded. Paging redraws the picker in place instead of stacking a spent prompt line per page (a settled answer still prints its `✔` record). Multi-select pickers keep already-checked items checked when more options load, and a failed "Load more…" no longer discards the options already on screen — retrying continues from where the list grew.

    ## 0.65.8 <a id="cli-0-65-8" />

    * *This release contains no user-facing changes.*

    ## 0.65.7 <a id="cli-0-65-7" />

    * *This release contains no user-facing changes.*

    ## 0.65.6 <a id="cli-0-65-6" />

    * Removed the `react` and `ink` runtime dependencies from the CLI, along with the `@types/react` dev dependency. The approval progress panel is now rendered directly using the terminal libraries already bundled with the CLI, so its appearance and behavior are unchanged while the installed dependency tree is significantly smaller.

    ## 0.65.5 <a id="cli-0-65-5" />

    * Code Substrate methods now use the `/code-substrate-runner` and `/code-substrate-workflows` API path prefixes across the SDK, the CLI, and the MCP server, and `sdk.context.api` and the CLI `curl` command accept paths built on them. The previous `/sdkdurableapi` and `/durableworkflowzaps` prefixes remain supported.

    ## 0.65.4 <a id="cli-0-65-4" />

    * The app `version` field is now optional in `.zapierrc` manifest entries. A versionless entry resolves to the latest implementation at runtime. The CLI's `build-manifest` and `add` commands no longer error when an app has no version, writing a versionless entry instead.

    ## 0.65.3 <a id="cli-0-65-3" />

    * `run-action --inputs '{...}'` no longer fetches the action's input fields or prompts to configure optional fields; provided inputs run exactly as given.

    ## 0.65.2 <a id="cli-0-65-2" />

    * *This release contains no user-facing changes.*

    ## 0.65.1 <a id="cli-0-65-1" />

    * *This release contains no user-facing changes.*

    ## 0.65.0 <a id="cli-0-65-0" />

    * * A command that invokes a deprecated SDK method now prints a styled
        deprecation notice.
      * The CLI disposes its SDK on exit, so telemetry flushes reliably.
      * `get-connection` now takes its connection as a required positional
        (`get-connection <connection>`) instead of an optional `--connection`
        flag, matching the SDK's now-required locator.
      * No other command-level changes.

    ## 0.64.1 <a id="cli-0-64-1" />

    * *This release contains no user-facing changes.*

    ## 0.64.0 <a id="cli-0-64-0" />

    * Graduated Triggers and Trigger Inbox methods from the experimental interface to the stable one. Every trigger method (`listTriggers`, `listTriggerInputFields`, `createTriggerInbox`, `ensureTriggerInbox`, `drainTriggerInbox`, `watchTriggerInbox`, the inbox lifecycle methods, and the message lease/ack/release methods) is now available directly from `@zapier/zapier-sdk` and the `zapier-sdk` CLI — no `/experimental` import, `--experimental` flag, or `ZAPIER_EXPERIMENTAL` env var required. On the default MCP server the request/response trigger tools (`create-trigger-inbox`, `list-triggers`, the lease/ack/release tools, etc.) are now listed; the callback-driven `drainTriggerInbox` and `watchTriggerInbox` remain SDK/CLI-only. They stay available via the experimental subpath and `zapier-sdk-experimental` binary for backward compatibility.

    ## 0.63.0 <a id="cli-0-63-0" />

    * Added `--callback-url` to `zapier-sdk login` and `zapier-sdk signup` for resuming pending non-interactive OAuth flows. Non-interactive login and signup now save pending state and exit immediately; run the same command later with `--callback-url <url>` to complete authentication from the browser callback URL.

      Login and signup telemetry now includes `used_non_interactive_mode` and `is_headless` on CLI command and auth lifecycle events.

    ## 0.62.0 <a id="cli-0-62-0" />

    * Deprecated `name` in favor of `key` for trigger inboxes. `name` continues to work as a deprecated alias.
      * `createTriggerInbox` now accepts an optional `key` parameter; `name` is deprecated.
      * `ensureTriggerInbox` now takes `key` as its required idempotency identifier; passing `name` still works but is deprecated.
      * `listTriggerInboxes` now accepts a `key` filter; the `name` filter is deprecated.
      * Trigger inbox locators (the `inbox` argument on `getTriggerInbox`, `updateTriggerInbox`, and related methods) now resolve non-UUID values by `key`.
      * Trigger inbox responses now include a `key` field alongside `name` (both hold the same value; `key` may be `null` when an inbox has no natural key).

    ## 0.61.3 <a id="cli-0-61-3" />

    * Decode JSON-string `input` on `triggerWorkflow` and `runDurable`. Their `input`
      field is freeform (`z.unknown()`), which the CLI surfaces as a raw string flag
      and never JSON-parses, so `--input '{"a":1}'` reached the API as a string and
      was double-encoded (server rejected it with `expected object, received string`).
      The input is now normalized at the schema boundary: a `{`/`[`-leading JSON
      string is decoded to its value, while objects and scalar strings pass through
      unchanged. This also fixes programmatic callers passing a JSON string.

    ## 0.61.2 <a id="cli-0-61-2" />

    * *This release contains no user-facing changes.*

    ## 0.61.1 <a id="cli-0-61-1" />

    * *This release contains no user-facing changes.*

    ## 0.61.0 <a id="cli-0-61-0" />

    * Add headless login mode to print a login URL and accept a pasted OAuth callback URL.

    ## 0.60.0 <a id="cli-0-60-0" />

    * Display trusted SDK deprecation notices from Zapier API responses. The SDK sniffs `zapier-sdk-deprecation-*` response headers (never on relay responses), warns once per notice id per process — with no opt-out — and emits an `api:deprecation_notice` event for wrappers. The CLI additionally renders notices as a boxed stderr warning after command output, and the MCP server attaches them to every tool result so agents relay the warning to users.

    ## 0.59.3 <a id="cli-0-59-3" />

    * Removed the deprecated `sdk.addPlugin(...)` chain method (and the `WithAddPlugin` type / chain-style no-arg `createSdk()` doorway). Extend a built SDK with the top-level `addPlugin(sdk, plugin)` instead.
    * `@zapier/zapier-sdk` now re-exports the plugin-authoring helpers: `createSdk`, `defineMethod`, `definePlugin`, `declareMethod`, `selectExports`, and `addPlugin`. Note: `createSdk` reuses the old name but now takes a root plugin, so a stale no-arg `createSdk()` call is a compile error rather than silent misbehavior.

    ## 0.59.2 <a id="cli-0-59-2" />

    * Fixed published type declarations that caused consumer TypeScript builds to fail with `Cannot find module` for a bundled-only dev dependency. Also fixed stray per-module declarations being published under `dist/src`.

    ## 0.59.1 <a id="cli-0-59-1" />

    * *This release contains no user-facing changes.*

    ## 0.59.0 <a id="cli-0-59-0" />

    * `triggerWorkflow` (and `trigger-workflow`) now authenticates with Zapier credentials and runs the workflow as the authenticated account; triggering is limited to workflows that account can access.

      Changed the `triggerWorkflow` response shape:

      | Before                       | After                                       |
      | ---------------------------- | ------------------------------------------- |
      | `{ workflow, status, body }` | `{ id, workflow_id, created_at }` on `data` |

      The call is unchanged: pass the workflow id and optional `input`.

    ## 0.58.3 <a id="cli-0-58-3" />

    * *This release contains no user-facing changes.*

    ## 0.58.2 <a id="cli-0-58-2" />

    * *This release contains no user-facing changes.*

    ## 0.58.1 <a id="cli-0-58-1" />

    * *This release contains no user-facing changes.*

    ## 0.58.0 <a id="cli-0-58-0" />

    * `listWorkflowRuns` (and `list-workflow-runs`) no longer return `output` on list items. Workflow-run lists no longer carry the (potentially large, soon-externalized) run output; fetch a single run's output via `getWorkflowRun` / `get-workflow-run`. Use `status` (`finished`/`failed`) to know when output is available.

    ## 0.57.1 <a id="cli-0-57-1" />

    * Surface trigger claim failure reason and workflow disable reason on the experimental `getWorkflow` / `listWorkflows` responses (and therefore the `get-workflow` / `list-workflows` CLI commands). Each `triggers[]` entry gains `error` (the latest claim's failure reason, present when `status` is `failed`), and the workflow gains a top-level `disabled_reason` (`trigger_claim_failed` when system-disabled, otherwise null). The two signals stay independent so an enabled workflow with a failed trigger is representable. Both fields are optional.

    ## 0.57.0 <a id="cli-0-57-0" />

    * *This release contains no user-facing changes.*

    ## 0.56.2 <a id="cli-0-56-2" />

    * CamelCase the input params on `runDurable` and `publishWorkflowVersion` (`sourceFiles`, `zapierDurableVersion`, `appVersions`, and the nested connection / app-version / trigger fields), keeping the old snake\_case names as deprecated aliases. Handlers map them back to the snake\_case wire body; output fields are unchanged.

    ## 0.56.1 <a id="cli-0-56-1" />

    * *This release contains no user-facing changes.*

    ## 0.56.0 <a id="cli-0-56-0" />

    * `listWorkflows` now paginates. `pageSize` (follows the SDK default page size; values above 100 are rejected) and `cursor` are honored in the SDK, and via the `list-workflows --page-size`/`--cursor` CLI flags that were previously no-ops. Iterating still returns all workflows; reading a single page now yields at most `pageSize` results rather than the full list.

    ## 0.55.8 <a id="cli-0-55-8" />

    * Rename `createWorkflow`'s `is_private` input to `private` to match `runDurable`, keeping `is_private` as a deprecated alias; the wire field stays `is_private`. Clarify the `run-durable` connections param description to show the required object shape.

    ## 0.55.7 <a id="cli-0-55-7" />

    * Add `createConnection` and two lower-level building blocks for connecting an app from code, end to end:

      * `createConnection({ app, browser?, timeoutMs?, pollIntervalMs? })` — high-level: mints a connection URL, prints it (and opens it in a browser when it's safe to do so), waits for the user to finish, and returns the new connection. `browser` is `"auto"` (default — opens locally, skips CI / SSH / headless Linux), `"always"`, or `"never"`. The URL is always printed, so a skipped or failed open falls back to copy/paste.
      * `getConnectionStartUrl({ app })` — low-level: mints a short-lived, signed start URL bound to the current user/account. Returns `{ url, startedAt, expiresAt, app }`.
      * `waitForNewConnection({ app, startedAt, timeoutMs?, pollIntervalMs? })` — low-level: polls until a connection for the app created at or after `startedAt` appears, then returns `{ id, app, title? }`. Throws `ZapierTimeoutError` after `timeoutMs` (default 5 minutes).

      `createConnection` is the right call for most cases. Reach for the two low-level methods when you want to hand off the URL without blocking (call `getConnectionStartUrl` alone), or do something custom between minting the URL and waiting — email it, post it to Slack, render a QR code — then call `waitForNewConnection`.
    * Add private-beta support for streaming auto-mode approval review messages and handling terminal failed approvals through the SDK and CLI. Auto mode is only enabled service-side for approved beta users.

    ## 0.55.6 <a id="cli-0-55-6" />

    * Response-field additions to experimental workflow and durable-run methods:
      * `updateWorkflow`, `getWorkflow`, `listWorkflows` responses now include `is_private`, `created_by_user_id`, and (where applicable) `triggers` with live claim status.
      * `publishWorkflowVersion`, `getWorkflowVersion`, `listWorkflowVersions` responses now include `trigger`, `connections`, and `app_versions`.
      * `runDurable` input accepts `notifications` (webhook subscribers for run lifecycle events).

    ## 0.55.5 <a id="cli-0-55-5" />

    * `login` now accepts a `--name` flag to label credentials without the interactive prompt — useful in CI and non-interactive environments. After trimming, the provided name is honored as given in both interactive and non-interactive modes — it is never auto-suffixed.

    ## 0.55.4 <a id="cli-0-55-4" />

    * *This release contains no user-facing changes.*

    ## 0.55.3 <a id="cli-0-55-3" />

    * Non-interactive `login` and `signup` now append an incrementing suffix (`<name>-1`, `<name>-2`, …) when the default credential name (`<email>@<hostname>`) already exists locally, instead of silently overwriting the existing credential's local entry and keychain secret. Interactive logins are unchanged.

    ## 0.55.2 <a id="cli-0-55-2" />

    * *This release contains no user-facing changes.*

    ## 0.55.1 <a id="cli-0-55-1" />

    * *This release contains no user-facing changes.*

    ## 0.55.0 <a id="cli-0-55-0" />

    * `watchTriggerInbox` now retries transient drain failures (5xx, 429,
      network blips) indefinitely with bounded backoff instead of rejecting
      on the first error; it still rejects immediately on fail-fast handler
      errors, `initialization_failure`, and permanent HTTP errors. When those
      retries persist long enough to saturate the backoff, it warns once on
      stderr (re-armed on recovery) so a stalled watch isn't silent.

      New `ApiClient.fetchJsonStream` (with the `JsonSseMessage` type): like
      `fetchStream` but JSON-parses each frame, surfacing a malformed frame
      as `{ parsed: false, data: null, raw }` instead of throwing, so one
      bad frame can't kill a long-lived stream. A non-ok response still
      throws the shared `ZapierError` subclasses before the first frame.

      Fixed: a fail-fast handler that throws a falsy value (`throw
      undefined`) is no longer silently swallowed, and a handler-thrown
      AbortError now rejects the watch instead of resolving it cleanly.

    ## 0.54.3 <a id="cli-0-54-3" />

    * *This release contains no user-facing changes.*

    ## 0.54.2 <a id="cli-0-54-2" />

    * Fixed logout so it reliably clears local authentication state even when the server cannot revoke the credential. Previously a failed revocation could abort logout and strand the user with credentials they could not remove. Re-login flows are unaffected; they still surface revocation failures before replacing credentials.

    ## 0.54.1 <a id="cli-0-54-1" />

    * *This release contains no user-facing changes.*

    ## 0.54.0 <a id="cli-0-54-0" />

    * Switched `watchTriggerInbox` from backoff polling to a Server-Sent Events subscription, so it now wakes on near-real-time inbox notifications instead of repeatedly polling for new messages.
      * The `maxDrainIntervalSeconds` option now controls a periodic safety drain that backstops the SSE stream — guaranteeing forward progress if events are missed or the connection drops — and its default changed from 60 to 300 seconds.
      * Real-time wake-up health is now reported on stderr: a warning when wake-ups pause and the watch falls back to the safety drain, plus transient reconnect notices in debug mode. stdout (including `--json` NDJSON output) is unaffected.
      * Added a `fetchStream` method to the API client, along with an exported `SseMessage` type, for opening Server-Sent Events connections through the standard request pipeline (auth, base URL, 429 retry, approval, and concurrency).

    ## 0.53.1 <a id="cli-0-53-1" />

    * *This release contains no user-facing changes.*

    ## 0.53.0 <a id="cli-0-53-0" />

    * Added `zapier-sdk signup` for browser-based account setup and local SDK credential provisioning.

    ## 0.52.12 <a id="cli-0-52-12" />

    * Route all debug, diagnostic, and telemetry log output to stderr (`console.error`) instead of stdout (`console.log`) across the SDK and CLI packages. The CLI now reserves stdout exclusively for the program's data payload — command output, JSON envelopes, response bodies — so callers can safely pipe CLI output through `jq`, `> redirect`, or `JSON.parse` even when `--debug` is on or telemetry/logging flags are enabled. Interactive terminal users see no change since both streams interleave in a TTY.
    * New stack-based composition surface for building on top of the SDK:
      `createZapierSdkStack(options)` (from the root and `/experimental`) returns
      the unsealed `PluginStack` that `createZapierSdk` materializes, and
      `createPluginStack`, `createCorePlugin`, and `addPlugin` are re-exported from
      the root. Build by chaining `.use(...)` and sealing with `.toSdk()`, or
      extend a sealed SDK in place with `addPlugin(sdk, plugin)`. The chain-style
      `createSdk().addPlugin(...)` pattern is deprecated (now logs a one-time
      warning) but still works.

      One behavior change: `normalizeError` no longer wraps thrown `Error` subclasses,
      so a handler's `TypeError` or a userland `MyAppError` bubbles through unchanged
      and `instanceof` works again; only non-`Error` throws get wrapped.

    ## 0.52.11 <a id="cli-0-52-11" />

    * Added `triggerWorkflow` (experimental) to fire a workflow's trigger with a user-supplied JSON payload. Only available via `@zapier/zapier-sdk/experimental`. The workflow id is UUID-validated at the input boundary; trigger endpoint failures (non-2xx, or workflow with no published version) surface as descriptive errors.

    ## 0.52.10 <a id="cli-0-52-10" />

    * Added `listWorkflowRuns`, `getWorkflowRun`, and `getTriggerRun` (experimental). All three live behind `@zapier/zapier-sdk/experimental` only — the stable subpath does not surface them. `listWorkflowRuns` is paginated; `getWorkflowRun` looks up a run by id; `getTriggerRun` walks from a trigger id to its associated run, useful immediately after firing a trigger when the caller has the trigger id but not yet the run id. All ID inputs are UUID-validated at the schema boundary. Consumers see any richer fields the server adds without an SDK release.

    ## 0.52.9 <a id="cli-0-52-9" />

    * Added `publishWorkflowVersion`, `listWorkflowVersions`, and `getWorkflowVersion` (experimental). All three are registered only in `@zapier/zapier-sdk/experimental`; the stable subpath does not expose them. `listWorkflowVersions` is paginated (cursor + pageSize); `publishWorkflowVersion` POSTs `source_files` (filename → contents) plus optional `dependencies`, `zapier_durable_version`, and `enabled` (defaults to true) to publish a new version; `getWorkflowVersion` returns the full version state including source files. Callers see any richer fields the server adds later without an SDK release. All ID inputs are UUID-validated at the boundary so non-UUID strings fail with a clear schema error.

    ## 0.52.8 <a id="cli-0-52-8" />

    * Added `runDurable` and `cancelDurableRun` (experimental). Both are registered only in `@zapier/zapier-sdk/experimental`; the stable subpath does not expose them. `runDurable` takes `source_files` (filename → contents) plus optional `input`/`dependencies`/`zapier_durable_version`/`connections`/`app_versions`, and a `private` flag. Returns the run ID immediately in `initialized` status — callers that need terminal status poll via `getDurableRun`; no built-in polling. `cancelDurableRun` returns `{ id, status: "cancelled" }` on success, and propagates `ZapierNotFoundError` (404) and `ZapierConflictError` (409 — run already terminal) so callers can distinguish those outcomes.

    ## 0.52.7 <a id="cli-0-52-7" />

    * Added `listDurableRuns` and `getDurableRun` (experimental). Both are registered only in `@zapier/zapier-sdk/experimental`; the stable subpath does not expose them. `listDurableRuns` is paginated (cursor + pageSize); `getDurableRun` returns the full run state with nested execution and operations journal. Callers see any richer fields the server adds later without an SDK release. The run id input is UUID-validated so non-UUID strings fail with a clear schema error.

    ## 0.52.6 <a id="cli-0-52-6" />

    * Fix login/logout reliability bugs.

      **Bug fixes:**

      * `logout` now warns and still clears local keychain/registry state when the server returns 401 during revocation (404 is still silently swallowed; 401 is surfaced as a console warning so users know to verify or revoke the credential manually if needed)
      * Re-login no longer fails with "already exists" when a locally-orphaned registry entry has the same name as the desired new credential
      * `logout` no longer prompts for confirmation before deleting credentials; it always proceeds immediately, which also fixes hangs in non-TTY/CI environments

      **Deprecations:**

      * `--skip-prompts` on `login` and `init` is deprecated in favour of `--non-interactive`. The old flag continues to work with a deprecation warning.
    * Added `createWorkflow`, `updateWorkflow`, `enableWorkflow`, `disableWorkflow`, and `deleteWorkflow` (experimental). All five are registered only in `@zapier/zapier-sdk/experimental`; the stable subpath does not expose them. `deleteWorkflow` prompts for explicit confirmation before the destructive call. The workflow id input is UUID-validated so non-UUID strings fail with a clear schema error. Callers see any richer fields the server adds later without an SDK release.

    ## 0.52.5 <a id="cli-0-52-5" />

    * Added `listWorkflows` and `getWorkflow` (experimental). Both are registered only in `@zapier/zapier-sdk/experimental`; the stable subpath does not expose them. `listWorkflows` is paginated with `pageSize`/`cursor`/`maxItems` options so callers can iterate via `for await (const page of sdk.listWorkflows())` or `toIterable(sdk.listWorkflows())`.

    ## 0.52.4 <a id="cli-0-52-4" />

    * *This release contains no user-facing changes.*

    ## 0.52.3 <a id="cli-0-52-3" />

    * *This release contains no user-facing changes.*

    ## 0.52.2 <a id="cli-0-52-2" />

    * Added `--skip-prompts` flag to the `login` command. When passed, the command skips all interactive prompts: it uses `email@hostname` as the credential name where possible, and errors instead of prompting when re-authentication or migration is required. Useful in CI environments, piped output, or any setup where TTY detection is unreliable.

    ## 0.52.1 <a id="cli-0-52-1" />

    * Added non-interactive support to the `login` command. When running in a headless environment (no TTY — such as CI, piped scripts, or an MCP server), `login` now automatically uses `email@hostname` as the credential name instead of hanging on interactive prompts. If re-authentication or migration is required and a terminal is unavailable, the command now exits with a clear error pointing to `logout` or an interactive terminal.

    ## 0.52.0 <a id="cli-0-52-0" />

    * Added a `trash` option to `listTableRecords` and `listTableFields` for controlling soft-deleted item visibility. Accepts `"exclude"` (default, active items only), `"include"` (active and soft-deleted), or `"only"` (soft-deleted items only).

    ## 0.51.3 <a id="cli-0-51-3" />

    * Restore `npx @zapier/zapier-sdk-cli` as a working entry point. Adding the `zapier-sdk-experimental` bin previously meant the package had multiple bins and none matched the unscoped package name, so npx could no longer pick one automatically. Aliasing `zapier-sdk-cli` to the same script as `zapier-sdk` fixes that.

    ## 0.51.2 <a id="cli-0-51-2" />

    * *This release contains no user-facing changes.*

    ## 0.51.1 <a id="cli-0-51-1" />

    * Clarified the `releaseOnError` option description for `drainTriggerInbox` and `consumeTriggerInbox`: errors release the message when the drain finishes, not immediately.

    ## 0.51.0 <a id="cli-0-51-0" />

    * Allow opting into approvals during login

    ## 0.50.0 <a id="cli-0-50-0" />

    * Add `hint?: string | string[]` to `PromptConfig.choices`. The CLI renders it after the choice's `name` as dimmed parens; an unset `hint` with a primitive `value` auto-renders the value.

      All built-in resolvers migrate to the new shape, so existing dropdowns get small visual cleanups (dim parens, no `ID:` prefix, dash converted to parens, em-dash in `tableRecordId` gone).

      Plugin authors who embed the value in `name` (e.g. `"Foo (${id})"`) should drop the embedded parens; the auto-default appends a second otherwise.

    ## 0.49.1 <a id="cli-0-49-1" />

    * Add optional `name` parameter to `createTriggerInbox` method

    ## 0.49.0 <a id="cli-0-49-0" />

    * Add type-to-filter to interactive single-select dropdowns: dynamic resolvers (apps, connections, tables, table records, etc.) and SELECT-format field choices. `(Load more...)` remains reachable even when a search yields zero matches, so users can pull the next page and try again.

      Dynamic resolvers also gain an `inputType: "search"` mode: the CLI prompts for free-form text, hands it to `fetch` as `search`, and either short-circuits on a primitive return (exact match) or renders results as a search-filterable dropdown. Empty results expose `(Use "foo" as-is)` and `(Try a different search)` so a required parameter can never strand the user. The built-in `appKey` resolver now uses this mode (`getApp` for exact match, `listApps --search` for fallback).

      `DynamicResolver` is now a discriminated union of `DynamicListResolver` and `DynamicSearchResolver`. Note for plugin authors: the `placeholder` field is now typed as `never` on the list variant, so a classic list resolver that was previously setting an unused `placeholder` will see a TypeScript error. Move it into a search-mode variant (`inputType: "search"`) or drop it — the CLI never read it on list resolvers.

    ## 0.48.2 <a id="cli-0-48-2" />

    * Trigger inbox fixes and additions:
      * Send `connection_id: null` for trigger inboxes without a connection so connection-less apps (e.g. tables) work correctly.
      * Add `listTriggers`, a read variant of `listActions` that lists an app's triggers.
      * Add interactive resolvers to trigger inbox message methods: `ackTriggerInboxMessages` and `releaseTriggerInboxMessages` prompt for `messages` with a multi-select of leased messages; `leaseTriggerInboxMessages` prompts for `leaseLimit` and `leaseSeconds`.
      * CLI: coerce static prompt input to the schema's underlying type so numeric/boolean fields (e.g. `leaseLimit`, `leaseSeconds`) no longer fail Zod validation with "expected number, received string".

    ## 0.48.1 <a id="cli-0-48-1" />

    * *This release contains no user-facing changes.*

    ## 0.48.0 <a id="cli-0-48-0" />

    * Default SDK auth to client credentials
    * Updated the experimental Triggers notice in all three package READMEs to clarify that the feature is in closed beta, with a link to contact us for access.

    ## 0.47.0 <a id="cli-0-47-0" />

    * Extend the `(Enter custom value)` sentinel to dynamic input-field dropdowns (SELECT-type fields). Selecting it falls through to a free-text prompt and returns the typed value, so users can supply values that aren't in the fetched dropdown (e.g. dynamic dropdowns that don't return every valid option). Single-select fields only; checkbox/multi-select fields are unchanged.

    ## 0.46.1 <a id="cli-0-46-1" />

    * Collapse the approval-flow surface into a single tri-state `approvalMode` option.

      What changed:

      * `approvalMode` is now `"disabled" | "poll" | "throw"` (was `"poll" | "fail"`).
      * `"disabled"` is the default. While the approval flow is alpha, callers must opt in explicitly via `approvalMode: "poll"` or `approvalMode: "throw"` (or the `ZAPIER_APPROVAL_MODE` env var). On an approval-required response, `"disabled"` throws a `ZapierApprovalError` with `status: "approval_required"` without creating an approval.
      * The `isInteractive` SDK option and the `ZAPIER_IS_INTERACTIVE` env var have been removed. Their role is subsumed by `approvalMode`: choosing `"poll"` / `"throw"` is the explicit opt-in that previously required `isInteractive: true`.
      * `"fail"` has been renamed to `"throw"` (both the option value and the `ZAPIER_APPROVAL_MODE` env var value). The behavior is unchanged: throw a `ZapierApprovalError` carrying the approval URL so the caller can surface it.
      * `approvalMode`, `approvalTimeoutMs`, and `maxApprovalRetries` are now part of the public API (no longer marked `internal: true`).

      There is no back-compat shim. `approvalMode: "fail"` and `isInteractive: <anything>` will fail Zod validation up front.

    ## 0.46.0 <a id="cli-0-46-0" />

    * Add `(Enter custom value)` sentinel to dynamic-resolver dropdowns in the CLI. Selecting it opens a free-text prompt and returns the typed value, so users can supply IDs that aren't in the fetched list without rerunning the command with a CLI flag. Shown for every single-select dynamic resolver; suppressed on checkbox (multi-select) prompts where a typed scalar can't merge with the user's other selections.

    ## 0.45.0 <a id="cli-0-45-0" />

    * Add experimental support for triggers.

    ## 0.44.1 <a id="cli-0-44-1" />

    * *This release contains no user-facing changes.*

    ## 0.44.0 <a id="cli-0-44-0" />

    * Adds an extension mechanism that lets the CLI and MCP server load additional plugin packages at runtime. Set `ZAPIER_SDK_EXTENSIONS` to a comma-separated list of package specifiers, or pass them via the new `extensions` option — methods they contribute show up automatically as CLI commands and MCP tools, no per-project wiring required.

      When a plugin tries to register a method, context field, or meta entry that's already registered by another plugin in the chain, `addPlugin` now logs a warning and skips the duplicate plugin's contribution rather than silently overwriting. This catches the common foot-gun of an extension accidentally shadowing a built-in SDK method. Intentional duplicates can be expressed via `composePlugins(...)`, and meta-only overrides (e.g. tagging a built-in method as deprecated) continue to work unchanged.

    ## 0.43.4 <a id="cli-0-43-4" />

    * *This release contains no user-facing changes.*

    ## 0.43.3 <a id="cli-0-43-3" />

    * *This release contains no user-facing changes.*

    ## 0.43.2 <a id="cli-0-43-2" />

    * *This release contains no user-facing changes.*

    ## 0.43.1 <a id="cli-0-43-1" />

    * Added `definePlugin`, `createPluginMethod`, and `createPaginatedPluginMethod` to reduce plugin authoring boilerplate.

    ## 0.43.0 <a id="cli-0-43-0" />

    * Rename the client credentials persistence seam from storage to cache and expose the CLI filesystem/keychain adapter as a best-effort cache.

    ## 0.42.2 <a id="cli-0-42-2" />

    * Convert API query params from camelCase to snake\_case (`appKeys` → `app_keys`, `pageSize` → `page_size`) to match the updated API contract.

    ## 0.42.1 <a id="cli-0-42-1" />

    * *This release contains no user-facing changes.*

    ## 0.42.0 <a id="cli-0-42-0" />

    * `registryPlugin` is now deprecated, because `getRegistry` is built into the SDK and added after each plugin is added. Plugins will always be registered; there is no need to call `createZapierSdkWithoutRegistry`, add custom plugins, and then `.addPlugin(registryPlugin)`. Because of this, `createZapierSdkWithoutRegistry` is now deprecated, and calling it will still give you an SDK with `getRegistry` on it. Calling `addPlugin(registryPlugin)` on that SDK is a no-op.

    ## 0.41.1 <a id="cli-0-41-1" />

    * *This release contains no user-facing changes.*

    ## 0.41.0 <a id="cli-0-41-0" />

    * Add an experimental interactive approval flow for policy-gated actions. When an action requires approval, the SDK detects the `approval_required` response, prompts for approval in interactive sessions, and automatically retries the original request once approved. Non-interactive sessions receive a clear error explaining that approval is required. This flow is experimental and its behavior may change in future releases.

    ## 0.40.1 <a id="cli-0-40-1" />

    * Simplify plugin system: plugins now receive sdk as a positional parameter with context at sdk.context. The Plugin type takes 2 generics (input SDK shape, output provides) instead of 3. Context is shallow-frozen to prevent reassignment of top-level properties. createSdk() is now zero-arg; SDK options are injected via createOptionsPlugin(options) through addPlugin like any other state. Plugins that need options declare it as an explicit context dependency. The addPluginOptions second argument to addPlugin has been removed.

    ## 0.40.0 <a id="cli-0-40-0" />

    * Support maxTime for SDK fetch & CLI curl - Relay extended timeout

    ## 0.39.11 <a id="cli-0-39-11" />

    * Fix connection resolution for no-auth apps

    ## 0.39.10 <a id="cli-0-39-10" />

    * *This release contains no user-facing changes.*

    ## 0.39.9 <a id="cli-0-39-9" />

    * Fix ZodObject param handling in CLI

    ## 0.39.8 <a id="cli-0-39-8" />

    * *This release contains no user-facing changes.*

    ## 0.39.7 <a id="cli-0-39-7" />

    * *This release contains no user-facing changes.*

    ## 0.39.6 <a id="cli-0-39-6" />

    * Hide the bundle-code command from CLI help and generated docs

    ## 0.39.5 <a id="cli-0-39-5" />

    * Fix empty input handling for optional params with placeholder

    ## 0.39.4 <a id="cli-0-39-4" />

    * Fix bug previously including envelope for curl with json input

    ## 0.39.3 <a id="cli-0-39-3" />

    * Connections - Replace isExpired with expired

    ## 0.39.2 <a id="cli-0-39-2" />

    * Make sure CLI only shows non-deprecated positional parameters.

    ## 0.39.1 <a id="cli-0-39-1" />

    CLI **flags and options** were renamed to match **[TypeScript SDK 0.40.1](#typescript-sdk-0-40-1)**—the same suffix-less resource naming, accepted values, and deprecation approach as in that release.

    **Note:** This is **not a breaking change**. The old flag names still work; they are **deprecated**.

    | Old flag / option   | New flag / option |
    | ------------------- | ----------------- |
    | `--app-key`         | `--app`           |
    | `--app-keys`        | `--apps`          |
    | `--action-key`      | `--action`        |
    | `--input-field-key` | `--input-field`   |
    | `--connection-id`   | `--connection`    |
    | `--connection-ids`  | `--connections`   |
    | `--table-id`        | `--table`         |
    | `--table-ids`       | `--tables`        |
    | `--record-id`       | `--record`        |
    | `--record-ids`      | `--records`       |
    | `--field-keys`      | `--fields`        |
    | `--account-id`      | `--account`       |
  </Tab>
</Tabs>
