Skip to main content

Token exchange

White label key concept: Token exchange is where Zapier uses your JWT’s user id and tenant/workspace id claims to just-in-time provision an opaque Zapier user and workspace under your partner account. Your end users don’t log into Zapier directly, and usage is billed to your partner account.
All flows below use the same OAuth token endpoint:
POST https://zapier.com/oauth/token
Use Content-Type: application/x-www-form-urlencoded and keep client_id / client_secret server-side.

Partner-signed JWT

Sign the JWT with RS256, RS384, RS512, ES256, ES384, or ES512. Zapier validates the signature using the public keys from your registered JWKS URL. Use a kid in the JWT header that matches your JWKS.

Example header

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "your-key-id"
}

Example payload

{
  "sub": "user_123",
  "org_id": "org_456",
  "iss": "https://accounts.your-app.com",
  "aud": "connect.zapier.com",
  "iat": 1711900000,
  "exp": 1711900300,
  "nbf": 1711900000
}
The exact names of the user id and tenant/workspace id claims are configured during partner onboarding (this example uses sub and org_id; yours might use e.g. tenant_id).

Common claims

For a successful token exchange, Zapier expects all of the claims in this table to be present and valid.
ClaimMeaning
subUser id in your system
org_id (example)Tenant / workspace / account id (claim name is configured with Zapier)
issIssuer — must match the value registered with Zapier
audAudience — must be connect.zapier.com
iatIssued-at (Unix seconds)
expExpiry — keep short (for example max ~5 minutes after iat)
nbfNot-before (typically same as iat)

Token types

User access token (Bearer)

A user access token is the White Label API token your backend uses to call Zapier APIs: list connections, Action Runs, trigger subscriptions, and so on. Treat it as a secret: never send it to the browser.

Connect token (Connect UI / MCP authorize)

A connect token is a short-lived (6m), single-use secret your backend obtains when you need to send the user through a browser flow (Connect UI for app connections, or the MCP authorization endpoint). Pass it only to your frontend for launching that flow (for example as the token query parameter on the Connect URL). Do not cache it long-term. When you request a connect token via POST /oauth/token, you must include resource: an absolute URL that identifies where the token will be used. It must be either https://connect.zapier.com/to/{app} (same Connect UI URL you open, including host) or https://mcp.zapier.com/api/v1/connect/{app} (the app’s MCP server URL / authorize resource). Zapier binds the token to that URL; ConnectApp sends the same resource when exchanging the token for a user session.
OAuth response shape: Token responses use the standard OAuth JSON field access_token for the issued secret — even when that secret is a connect token, not a user access token. That is because POST /oauth/token serves multiple grant types and token types with one response envelope. In your code, read the connect token from access_token in the JSON body and name it clearly (for example connectToken) in your application.

A) Actions API / Triggers API (embedded)

Use a user access token for all server-side API calls. When you need Connect UI, obtain a connect token in a second exchange using that user access token. 1) JWT → user access token
curl -X POST https://zapier.com/oauth/token \
  -d grant_type=urn:ietf:params:oauth:grant-type:token-exchange \
  -d client_id=<ZAPIER_CLIENT_ID> \
  -d client_secret=<ZAPIER_CLIENT_SECRET> \
  -d subject_token=<YOUR_JWT> \
  -d subject_token_type=urn:ietf:params:oauth:token-type:external-jwt \
  -d requested_token_type=urn:ietf:params:oauth:token-type:access-token \
  -d "scope=connection:read action:run zap zap:write"
Example scopes above are illustrative; your onboarding may specify a different scope string. 2) User access token → connect token When the user must connect or reconnect an app, exchange the user access token for a connect token. Set resource to the Connect UI URL you will open (example uses the production Connect host and implementation id):
curl -X POST https://zapier.com/oauth/token \
  -d grant_type=urn:ietf:params:oauth:grant-type:token-exchange \
  -d client_id=<ZAPIER_CLIENT_ID> \
  -d client_secret=<ZAPIER_CLIENT_SECRET> \
  -d subject_token=<USER_ACCESS_TOKEN> \
  -d subject_token_type=urn:ietf:params:oauth:token-type:access-token \
  -d requested_token_type=urn:ietf:params:oauth:token-type:connect-token \
  -d scope=connection:write \
  -d resource=https://connect.zapier.com/to/<APP_IMPLEMENTATION_ID>
Exact parameters for the second hop (including scope) can depend on your partner configuration. If something fails, verify the scopes and token types enabled for your OAuth client with Zapier.
Use the connect token in access_token from the response as the token query parameter when opening Connect UI.

B) MCP (AI agent connections)

For MCP, you typically do not need a White Label user access token before opening the MCP authorization step. Exchange the partner-signed JWT directly for a connect token, then run the MCP OAuth authorization-code flow; the MCP access token you use against the MCP server comes from that flow (see AI agent connections & automations). JWT → connect token (MCP) Use the app’s mcp_server_url as resource (the same value you pass as the resource query parameter on the MCP authorize URL):
curl -X POST https://zapier.com/oauth/token \
  -d grant_type=urn:ietf:params:oauth:grant-type:token-exchange \
  -d client_id=<ZAPIER_CLIENT_ID> \
  -d client_secret=<ZAPIER_CLIENT_SECRET> \
  -d subject_token=<YOUR_JWT> \
  -d subject_token_type=urn:ietf:params:oauth:token-type:external-jwt \
  -d requested_token_type=urn:ietf:params:oauth:token-type:connect-token \
  -d scope=connection:write \
  -d resource=<MCP_SERVER_URL>
Again, the connect token is returned in the JSON field access_token.

User and workspace provisioning

Zapier maps your JWT claims to a user and workspace under your partner account. The first time a new combination of configured claim values appears in a token exchange, Zapier just-in-time provisions that workspace and user. Later exchanges with the same mapping reuse them.

Output and next steps

  • User access token: keep server-side only; use as Authorization: Bearer for Zapier APIs.
  • Connect token: pass to the browser only to start Connect UI or the MCP authorize URL. Single-use and short-lived — generate a fresh one each time you start a connection flow.

Refreshing tokens

When an MCP access token expires (expires_in is typically 3600 seconds / 1 hour), use the refresh_token to obtain a new one without requiring the user to re-authorize. See AI agent connections — Refresh the MCP access token for the request format.
Each refresh returns a new refresh_token. Always store and use the latest one — previous refresh tokens are invalidated.
For error responses during refresh, see Error handling. Next: Connection flow for popup vs redirect, reconnect, and callback parameters. For MCP, continue with AI agent connections & automations.