zapier-sdk

star 3

Guide for using the Zapier SDK and CLI to explore apps, discover actions, and run authenticated API calls against 9,000+ connected apps. Trigger when the user mentions the Zapier SDK, zapier-sdk, @zapier/zapier-sdk, wants to call a connected app's API through Zapier's auth infrastructure, run a one-off action via CLI (Slack message, Google Sheet, HubSpot lookup), make authenticated fetch/curl requests through Zapier, or list connected apps. Also trigger for using the SDK inside a Code by Zapier step — the @zapier/zapier-sdk toggle, the connections[] runtime map, calling zapier.apps.X or zapier.fetch from a Code step, or collapsing a multi-branch / multi-sub-zap workflow into one Code step. This skill is for CONSUMING Zapier's pre-built connectors, NOT for BUILDING new Zapier integrations (that's zapier-platform-cli and zapier-platform-ui).

work-flowers By work-flowers schedule Updated 5/27/2026

name: zapier-sdk description: "Guide for using the Zapier SDK and CLI to explore apps, discover actions, and run authenticated API calls against 9,000+ connected apps. Trigger when the user mentions the Zapier SDK, zapier-sdk, @zapier/zapier-sdk, wants to call a connected app's API through Zapier's auth infrastructure, run a one-off action via CLI (Slack message, Google Sheet, HubSpot lookup), make authenticated fetch/curl requests through Zapier, or list connected apps. Also trigger for using the SDK inside a Code by Zapier step — the @zapier/zapier-sdk toggle, the connections[] runtime map, calling zapier.apps.X or zapier.fetch from a Code step, or collapsing a multi-branch / multi-sub-zap workflow into one Code step. This skill is for CONSUMING Zapier's pre-built connectors, NOT for BUILDING new Zapier integrations (that's zapier-platform-cli and zapier-platform-ui)."

Zapier SDK — Explore Apps and Run Actions

The Zapier SDK gives you programmatic access to Zapier's full app ecosystem. Any API call, on behalf of a user, with no OAuth setup. Zapier handles auth, token refresh, retries, and API quirks across 9,000+ integrations.

Current versions: SDK 0.40.1 / CLI 0.39.1 (open beta, free during early access)

When to Use This Skill vs Others

This skill is for consuming Zapier's pre-built connectors — calling Slack, Google Sheets, Salesforce, etc. through Zapier's auth layer using the SDK or CLI.

The zapier-platform-cli and zapier-platform-ui skills are for building new Zapier integrations (creating custom triggers, actions, and auth flows that get published to Zapier's app directory). Those are a completely different product.

Rule of thumb: if the user wants to call an app's API, use this skill. If they want to build an integration that appears in Zapier's app catalog, use the Platform skills.

Prerequisites

  • Node.js 20+
  • npm install @zapier/zapier-sdk (runtime)
  • npm install -D @zapier/zapier-sdk-cli @types/node typescript (dev/CLI)
  • Logged in (see authentication section below)
  • At least one connected app at https://zapier.com/app/assets/connections

Authentication — Local vs Headless Environments

The SDK/CLI needs Zapier credentials. How you provide them depends on the environment:

Local terminal or Claude Code (has a browser):

npx zapier-sdk login

This opens a browser for OAuth. Credentials are stored at ~/.config/zapier-sdk-cli-nodejs/config.json.

Cowork, CI/CD, or any headless environment (no browser):

Browser-based login won't work here. Use client credentials instead:

  1. Generate credentials once from a local machine where you can open a browser:

    npx zapier-sdk create-client-credentials "cowork"
    

    Save the client_id and client_secret immediately — the secret is shown only once.

  2. Use them in Cowork by passing the flags to any CLI command:

    npx zapier-sdk list-connections \
      --credentials-client-id YOUR_CLIENT_ID \
      --credentials-client-secret YOUR_SECRET \
      --owner me --json
    

    Or export them as environment variables to avoid repeating the flags:

    export ZAPIER_CLIENT_ID="your_client_id"
    export ZAPIER_CLIENT_SECRET="your_client_secret"
    npx zapier-sdk list-connections --owner me --json
    

For the TypeScript SDK, pass them at initialisation under a credentials object:

const zapier = createZapierSdk({
  credentials: {
    clientId: process.env.ZAPIER_CLIENT_ID,
    clientSecret: process.env.ZAPIER_CLIENT_SECRET,
  },
});

// Or pass a token directly:
const zapier = createZapierSdk({ credentials: process.env.ZAPIER_TOKEN });

The old top-level clientId/clientSecret/token props are deprecated — use credentials in new code.

CLI Workflow — The Core Loop

The CLI is the fastest way to explore what's possible and run one-off actions. The typical workflow goes: find app → find connection → discover actions → inspect inputs → run action.

1. Find the App

npx zapier-sdk list-apps --search "slack" --json

This returns app metadata including the slug (e.g. slack, google-sheets). Use the slug in all subsequent commands.

2. Find Your Connection

The app slug is a positional argument, not a flag:

npx zapier-sdk list-connections slack --owner me --json

Or to get the first non-expired match directly:

npx zapier-sdk find-first-connection slack --owner me --json

Non-expired connections are returned by default. Pass --expired to filter to expired-only (useful for spotting connections that need re-auth).

Each connection has a numeric id — you'll pass this as --connection (or the older --connection-id) when running actions.

3. Discover Actions

# All actions for an app
npx zapier-sdk list-actions slack --json

# Filter by type: read, write, or search
npx zapier-sdk list-actions slack --action-type write --json

# Get details on a specific action
npx zapier-sdk get-action slack write channel_message --json

Action types:

  • write — create or update data (send a message, create a record)
  • search — find existing data (look up a user, find a row)
  • read — list data (list channels, list spreadsheets)

4. Inspect Input Fields

Before running an action, check what inputs it needs:

npx zapier-sdk list-action-input-fields slack write channel_message \
  --connection 12345 --json

Some fields are dynamic — they only appear after you provide earlier fields. For example, Google Sheets column fields only appear once you specify the spreadsheet:

npx zapier-sdk list-action-input-fields google-sheets write add_row \
  --connection 12345 \
  --inputs '{"spreadsheet": "abc123", "worksheet": "0"}' \
  --json

For dynamic dropdowns (e.g. choosing a channel from a list):

npx zapier-sdk list-action-input-field-choices slack write channel_message channel \
  --connection 12345 --json

For JSON Schema output (useful for agent tool definitions):

npx zapier-sdk get-action-input-fields-schema slack write channel_message \
  --connection 12345 --json

Note: the actual CLI commands are list-action-input-fields, list-action-input-field-choices, and get-action-input-fields-schema (with the action- prefix). The shorter names without action- do not exist.

5. Run the Action

npx zapier-sdk run-action slack write channel_message \
  --connection 12345 \
  --inputs '{"channel": "C0123ABCD", "text": "Hello from the SDK!"}' \
  --json

6. Direct API Calls (Going Beyond Pre-built Actions)

When the pre-built actions don't cover your use case, use curl to make authenticated HTTP requests directly:

npx zapier-sdk curl "https://slack.com/api/users.list" \
  --connection 12345

POST with JSON body:

npx zapier-sdk curl "https://api.example.com/endpoint" \
  --connection 12345 \
  -X POST \
  --json '{"key": "value"}'

The connection ID tells Zapier which stored credentials to inject (OAuth tokens, API keys, etc.). No manual header management needed.

Governance note: Pre-built actions respect your org's app/action restrictions. Direct API calls via curl/fetch are not yet governed — direct API governance is on the roadmap. See the "Approval flow and governance" section below for the related approval mechanism.

Scripting with the CLI

All commands support --json for piping. Common pattern — extract a connection ID and use it:

CONNECTION_ID=$(npx zapier-sdk find-first-connection google-sheets --owner me --json 2>/dev/null | jq -r '.data.id')

npx zapier-sdk run-action google-sheets write create_spreadsheet \
  --connection $CONNECTION_ID \
  --inputs '{"title": "My Sheet", "headers": ["Name", "Email"]}' \
  --json

TypeScript SDK — For Production Code

When you need something repeatable, embedded, or in production, use the TypeScript SDK. See typescript-sdk.md for the full API reference.

Quick example:

import { createZapierSdk } from "@zapier/zapier-sdk";

const zapier = createZapierSdk();

// Find connection (non-expired by default)
const { data: conn } = await zapier.findFirstConnection({
  app: "slack", owner: "me",
});

// Bind connection to app
const slack = zapier.apps.slack({ connection: conn.id });

// Run action
const { data: result } = await slack.write.channel_message({
  inputs: { channel: "C0123ABCD", text: "Hello from the SDK!" },
});

Inside Code by Zapier — SDK in a Code Step

The SDK can also run inside a JavaScript Code step in any Zap, with full access to your existing app connections — no embedded API keys, no client credentials. This is the right surface when the goal is to collapse a tangle of paths, loops, or sub-zaps into a single Code step inside the same Zap, where the visual editor has become unwieldy.

Enabling the SDK in a Code step

  1. In the Zap editor, add a Code by Zapier step → event Run JavaScriptOpen in Code Editor.
  2. Click the Packages icon in the left sidebar.
  3. Toggle @zapier/zapier-sdk (latest) on. Zapier rewrites the step with a scaffold that imports the SDK, initialises zapier, and wraps your code in a main function:
import { createZapierSdk } from '@zapier/zapier-sdk';
const zapier = createZapierSdk();

/**
 * @param {{inputData: InputData}}
 */
export default async function main({ inputData }) {
  // this is wrapped in an `async` function — use await throughout
  return { hello: "world" };
}

Put your per-run logic inside main, and keep constants and helper functions at module scope (above main) so they aren't rebuilt on every invocation. Whatever object you return becomes the step's output.

connections is a runtime global, not a main argument. The scaffold only destructures { inputData }, but Zapier also injects a connections map at module scope (alongside zapier). Reference it directly — connections["slack"]. Do not add it to the main({ inputData }) destructure: a destructured connections would be undefined and shadow the real global.

The SDK is JavaScript only — Python Code steps don't support it. Code triggers (the trigger variant of Code by Zapier) also don't support the SDK; it's actions only.

Wiring connections

Connections are wired through the UI, not in code:

  1. Click Add app connection+ Add connection.
  2. Search for and select the app.
  3. Select an existing connected account from the Select account connection dropdown (or connect a new one).
  4. The Account ID Variable field auto-fills with a readable key based on the account label — for example slack, google_sheets, notion, chatgpt. You can edit this to anything (e.g. slack_personal, sheets_reporting); each key just needs to be unique within the step.

That key becomes the lookup into a runtime connections map exposed inside the Code step. You don't see connection IDs anywhere in your code — Zapier resolves the key to the underlying connection at runtime, and credentials never appear in the code, the Zap history, or logs.

Repeat for each app you want the step to call. Only the Zap owner can add or edit connections on the step; collaborators without access to the selected connections can't edit the step.

Calling actions

Two patterns. Both work; pick whichever reads better for the step.

The snippets below go inside main (see the scaffold above); zapier and connections come from module scope.

Proxy pattern — bind the connection to an app once, then call actions cleanly:

const notion = zapier.apps.notion({ connectionId: connections["notion"] });

const { data: page } = await notion.write.create_database_item({
  inputs: {
    database: "DB_ID",
    title: inputData.title,
  },
});

return { pageId: page.id };

Direct runAction pattern — useful when you want a single call, want the action key to be dynamic, or want to keep things flat:

const { data } = await zapier.runAction({
  appKey: "notion",
  actionType: "write",
  actionKey: "create_database_item",
  connectionId: connections["notion"],
  inputs: {
    database: "DB_ID",
    title: inputData.title,
  },
});

The newer suffix-less parameter names (app / action / connection) also work and are preferred in fresh code outside Code steps; the help article still uses the older appKey/actionKey/connectionId names, which is why the example above mirrors them.

Direct authenticated HTTP via zapier.fetch

When the pre-built actions don't cover the endpoint, call the API directly. Zapier injects the connection's stored credentials (OAuth token, API key, signed headers — whatever the connection uses):

const res = await zapier.fetch("https://api.notion.com/v1/databases/DB_ID/query", {
  method: "POST",
  connection: connections["notion"],
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ page_size: 50 }),
});
const result = await res.json();

zapier.fetch also accepts callbackUrl (for async responses to long-running operations) and maxTime (max seconds to wait for a response, honoured on a best-effort basis). It's the escape hatch for the long tail of endpoints that don't have a pre-built action.

Discovering app keys, action keys, and input fields

The Code step UI doesn't tell you what to type. To find the right appKey, actionKey, and input field names, run the SDK CLI locally against the same Zapier account, then transcribe the values into your Code step. The CLI is the canonical discovery tool for this — see the CLI Workflow section above. Typical recipe:

npx zapier-sdk list-connections --owner me --json     # confirm app keys
npx zapier-sdk list-actions notion --json             # find action keys
npx zapier-sdk list-action-input-fields notion write create_database_item \
  --connection 12345 --json                            # find input field names

You don't pass the --connection value into the Code step — it's only needed locally so the CLI can resolve dynamic fields. In the Code step, the value comes from connections["notion"].

Limits and gotchas

  • JavaScript only. Python Code steps don't support the SDK.
  • Your code lives inside main. The scaffold is export default async function main({ inputData }) { … } — per-run logic goes inside; constants/helpers at module scope. Earlier docs implied a bare top-level body; it's a wrapped function.
  • connections is a module-scope global, not a main argument. Reference connections["key"] directly; never add connections to the main({ inputData }) destructure or the undefined param shadows the real global.
  • Actions only. The SDK is not available in Code triggers. Triggers / event subscriptions inside Code steps are on the roadmap, not yet shipped.
  • Per-step runtime caps still apply. Same memory and wall-clock limits as any Code step — up to ~10 minutes on paid plans. Long-running scrapes or sync jobs that exceed this should run externally.
  • Direct zapier.fetch calls aren't yet covered by org governance. Pre-built actions respect your org's app/action restrictions; raw API calls don't yet. Direct API governance is on the roadmap.
  • Credentials never appear in code, Zap history, or logs. Expired or invalid connections produce a runtime error — re-authenticate in the Zap editor.
  • Owner-only edits. Only the Zap owner can add or change connections on the step.

When to prefer this over external SDK use

Reach for SDK-in-Code-step when:

  • You're already inside a Zap and the logic has outgrown Paths / Filters / Looping by Zapier — multi-branch routing, nested loops, conditional retries — and the visual editor has become hard to read.
  • You'd otherwise build several sub-zaps stitched together with webhooks just to get the control flow right. One Code step with the SDK is usually clearer and cheaper.
  • The work is naturally part of this Zap's run (triggered by this trigger, using this run's data) and doesn't need to live in a separate codebase.

Reach for the external SDK / CLI when the work is scheduled, long-running, agentic, lives in a product, or needs a real test/deploy lifecycle.

Authentication Options

Method When to Use Setup
In a Code step Logic that belongs inside a specific Zap Toggle @zapier/zapier-sdk (latest) on in the Code editor's Packages panel; wire connections via the UI. No login or credentials needed.
Browser login Local terminal, Claude Code npx zapier-sdk login
Client credentials Cowork, CI/CD, servers, headless npx zapier-sdk create-client-credentials "my-app" — save the secret immediately, it's shown only once. Pass via --credentials-client-id and --credentials-client-secret flags.
Direct token Partner OAuth, internal use Pass token directly to createZapierSdk()

Zapier Tables

The SDK/CLI can also work with Zapier Tables (structured data storage). See tables.md for details.

Common Patterns

Send yourself a Slack DM:

# Look up your Slack user by email
npx zapier-sdk run-action slack search user_by_email \
  --connection ID --inputs '{"email": "you@example.com"}' --json

# Send DM using the returned username
npx zapier-sdk run-action slack write direct_message \
  --connection ID --inputs '{"channel": "USERNAME", "text": "Hello!"}' --json

Create a Google Sheet and add rows:

# Create sheet
npx zapier-sdk run-action google-sheets write create_spreadsheet \
  --connection ID --inputs '{"title": "Report", "headers": ["Name", "Score"]}' --json

# Inspect dynamic column fields
npx zapier-sdk list-action-input-fields google-sheets write add_row \
  --connection ID --inputs '{"spreadsheet": "SHEET_ID", "worksheet": "0"}' --json

# Add a row (use the dynamic column keys from above, e.g. COL$A, COL$B)
npx zapier-sdk run-action google-sheets write add_row \
  --connection ID \
  --inputs '{"spreadsheet": "SHEET_ID", "worksheet": "0", "COL$A": "Alice", "COL$B": "95"}' \
  --json

Search then act pattern:

# Find a contact in HubSpot
npx zapier-sdk run-action hubspot search contact --connection ID \
  --inputs '{"email": "alice@example.com"}' --json

# Use the result to update or create something elsewhere

Gotchas and Tips

  • Parameter naming: As of SDK v0.40.1 / CLI v0.39.1, parameters use suffix-less names (--app not --app-key, --connection not --connection-id, app not appKey in SDK options, etc.). The old names still work but are deprecated.
  • App identifiers are flexible. Anywhere an app parameter is accepted, you can pass a slug (slack), implementation name (SlackCLIAPI), or versioned ID (slack@1.2.3). The slug is what you'll use 99% of the time.
  • --app for connection commands is a positional, not a flag. find-first-connection slack --owner me, not find-first-connection --app slack.
  • Enterprise/Team plans are off by default for the SDK — contact Zapier for opt-in.
  • --json flag is your friend — always use it when scripting or piping output.
  • Dynamic fields are the most common point of confusion. If an action seems to be missing expected inputs, try passing the fields you already know via --inputs to list-action-input-fields to reveal the dynamic ones.
  • Connection IDs are numeric — don't confuse them with app slugs.
  • Timeout default is 180 seconds for action execution. Override with --timeout-ms.
  • Pagination: Use --page-size and --cursor for large result sets. The default page size is 100.
  • Expired connections are filtered out by default. Pass --expired to filter to expired-only (useful for spotting connections that need re-auth).

Approval Flow and Governance

When an org policy gates an action, the SDK can throw a ZapierApprovalError or, with the right flag, create an approval and wait for the user to grant it. New global CLI flags control this:

  • --approval-mode disabled (default) — throws ZapierApprovalError on approval-required responses without creating an approval.
  • --approval-mode poll — creates the approval, opens it in a browser, polls until resolved, and retries the original request.
  • --approval-mode throw — creates the approval and throws ZapierApprovalError with the approval URL so the caller can surface it (e.g. to a chat UI).
  • --approval-timeout-ms — timeout for polling (default 600 000 ms / 10 min).
  • --max-approval-retries — max sequential approval rounds per request (default 2).

You can also set the ZAPIER_APPROVAL_MODE env var instead of passing the flag every time.

Related capability flags that act as explicit opt-ins for sensitive operations:

  • --can-include-shared-connections — allow listing shared connections.
  • --can-include-shared-tables — allow listing shared tables.
  • --can-delete-tables — allow deleting tables.

This is the governance answer to the existing "direct fetch calls aren't yet covered by org policy" caveat — approval-mode lets a server/agent run gated actions while still keeping a human in the loop.

Triggers API (Experimental)

Real-time triggers let code react to events from any of the 9,000+ connected apps without polling or custom webhook infrastructure. Available as an experimental opt-in — methods and behaviour may change between versions.

Opting in

Import experimental SDK methods from @zapier/zapier-sdk/experimental (the factory is still createZapierSdk):

import { createZapierSdk } from "@zapier/zapier-sdk/experimental";

const zapier = createZapierSdk();

For the CLI, any one of these works:

npx zapier-sdk-experimental --help    # dedicated bin
npx zapier-sdk --experimental --help  # flag on stable bin
ZAPIER_EXPERIMENTAL=true npx zapier-sdk --help  # env var

Core concepts

  • Trigger — an event source defined by an integration (e.g. Slack channel_message). Discover with listTriggers.
  • Trigger inbox — a server-side subscription for a specific (app, action, connection, inputs) tuple. Zapier connects to the app and buffers events.
  • Message — a buffered event. Has id, created_at, payload (raw event data), and message_attributes with lease_count, error_message, and possible_duplicate_data.
  • Lease → ack → release — messages are leased (hidden from other consumers) while processing, then acked (permanently removed) on success or released back to the pool on failure.

Inbox lifecycle: initializingactivepauseddeleting, with initialization_failure as a terminal failure state. Check paused_reason if an inbox isn't active.

Discovery — find triggers and required inputs

Mirrors the action discovery loop. Use listTriggers to find what an app exposes, then listTriggerInputFields to see what the subscription needs:

npx zapier-sdk-experimental list-triggers slack --json
npx zapier-sdk-experimental list-trigger-input-fields slack channel_message \
  --connection 12345 --json
const { data: triggers } = await zapier.listTriggers({ app: "slack" });
const { data: fields } = await zapier.listTriggerInputFields({
  app: "slack",
  action: "channel_message",
  connection: connId,
});

Ensure an inbox (idempotent by name)

ensureTriggerInbox is the production-safe choice — re-running with the same name returns the existing inbox instead of creating a duplicate. Use createTriggerInbox only for throwaway inboxes with auto-generated names.

const { data: inbox } = await zapier.ensureTriggerInbox({
  name: "my-slack-inbox",
  app: "slack",
  action: "channel_message",
  connection: connId,
  inputs: { channel: "C0123ABC456" },
});
npx zapier-sdk-experimental ensure-trigger-inbox my-slack-inbox slack channel_message \
  --connection 12345 \
  --inputs '{"channel": "C0123ABC456"}'

Drain once vs watch continuously

drainTriggerInbox leases all currently-available messages, runs your handler against each, and resolves when the inbox is empty. Right for cron jobs, scripts, or webhook handlers.

watchTriggerInbox wraps drain in a poll loop with exponential backoff. Right for long-running consumers.

const controller = new AbortController();
process.on("SIGTERM", () => controller.abort());
process.on("SIGINT", () => controller.abort());

await zapier.watchTriggerInbox({
  inbox: "my-slack-inbox",
  onMessage: async (msg) => {
    const { text, user, channel } = msg.payload as { text: string; user: string; channel: string };
    console.log(`[${channel}] ${user}: ${text}`);
  },
  releaseOnError: true,
  concurrency: 5,
  signal: controller.signal,
});

Aborting the controller cancels in-flight requests, releases unprocessed messages back to the inbox, and resolves cleanly (doesn't reject). Wire it to SIGTERM/SIGINT for graceful shutdown.

CLI equivalents pipe each message as JSON to your handler:

npx zapier-sdk-experimental drain-trigger-inbox my-slack-inbox \
  --exec node -- ./handle-message.js

npx zapier-sdk-experimental watch-trigger-inbox my-slack-inbox \
  --exec node -- ./handle-message.js

Use --exec-shell instead when you need pipes, redirects, or env expansion.

Error handling and the quarantine threshold

Default behaviour is fail-fast — the first handler throw rejects the whole drain. Common knobs:

  • releaseOnError: true — release failed messages back to the pool when the drain finishes, instead of waiting out the full lease timeout.
  • continueOnError: true — keep draining when a handler throws. Errors route to an optional onError(error, message) observer. SDK-level errors (HTTP failures on lease/ack/release) still reject regardless.

Two control-flow signals give per-message control without rejecting the drain:

import { ZapierReleaseTriggerMessageSignal, ZapierAbortDrainSignal } from "@zapier/zapier-sdk/experimental";

await zapier.drainTriggerInbox({
  inbox: "my-slack-inbox",
  onMessage: async (msg) => {
    if (looksMalformed(msg.payload)) throw new ZapierReleaseTriggerMessageSignal(); // release this one, continue
    if (shouldStop()) throw new ZapierAbortDrainSignal(); // finish current batch, resolve cleanly
    await handle(msg);
  },
});

Quarantine at lease_count = 5. Once a message has been leased 5 times without being acked, Zapier quarantines it — it stops appearing in lease/drain/watch but remains visible in listTriggerInboxMessages. There's no end-user mechanism to recover a quarantined message today. Defend by detecting poison messages in onMessage and explicitly acking them before they hit the threshold:

onMessage: async (msg) => {
  if (msg.message_attributes.lease_count >= 3 && isKnownPoison(msg)) {
    // Don't throw — returning acks the message and drops it.
    console.warn(`Dropping poison message ${msg.id}`);
    return;
  }
  await handle(msg);
}

Pair with continueOnError: true so one bad message doesn't bring down the drain.

Push instead of poll: notificationUrl

Running a server with a public endpoint? Pass notificationUrl when creating the inbox and Zapier POSTs to that URL whenever new messages arrive. Your endpoint calls drainTriggerInbox on demand — no poll loop, no backoff delay.

await zapier.ensureTriggerInbox({
  name: "my-slack-inbox-push",
  app: "slack",
  action: "channel_message",
  connection: connId,
  inputs: { channel: "C0123ABC456" },
  notificationUrl: "https://my-server.example/trigger-webhook",
});

updateTriggerInbox can change the notificationUrl on an existing inbox.

Inbox management

await zapier.listTriggerInboxes({ status: "active" });
await zapier.pauseTriggerInbox({ inbox: "my-slack-inbox" });   // stops collection, preserves buffered messages
await zapier.resumeTriggerInbox({ inbox: "my-slack-inbox" });  // restarts collection
await zapier.deleteTriggerInbox({ inbox: "my-slack-inbox" });  // cancels subscription

Production deployment

For long-running watchers, run under a process supervisor that restarts on crash and sends SIGTERM on stop so graceful shutdown runs:

  • Linux servers — systemd
  • macOS dev — launchd, or brew services
  • Node-native — pm2 (cross-platform, simplest for Cowork / CI-managed boxes)

For headless deployment, use client credentials — same setup as for actions.

Complete method list

Discovery: listTriggers, listTriggerInputFields, listTriggerInputFieldChoices.

Inbox management: createTriggerInbox, ensureTriggerInbox, listTriggerInboxes, getTriggerInbox, updateTriggerInbox, pauseTriggerInbox, resumeTriggerInbox, deleteTriggerInbox.

Message processing: drainTriggerInbox, watchTriggerInbox (high-level); leaseTriggerInboxMessages, ackTriggerInboxMessages, releaseTriggerInboxMessages, listTriggerInboxMessages (primitives).

All available as CLI subcommands via the zapier-sdk-experimental bin. Full walkthrough at https://docs.zapier.com/sdk/triggers.

Reference Files

  • typescript-sdk.md — Full TypeScript SDK API reference (methods, types, pagination, app proxy pattern)
  • cli-reference.md — Complete CLI command reference with all flags
  • tables.md — Working with Zapier Tables (create, query, update records)
Install via CLI
npx skills add https://github.com/work-flowers/skills --skill zapier-sdk
Repository Details
star Stars 3
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator
work-flowers
work-flowers Explore all skills →