> ## 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.

# Permissions

> Build up a permission policy for your SDK clients as your code does new things

SDK Permissions let you put guardrails on what your SDK clients can do. When your code makes a request that isn't covered by your policy, the SDK pauses and asks you to approve or deny it. Approvals build up into reusable rules over time, so the same prompts don't fire twice.

<Warning>
  **Experimental, opt-in.** SDK Permissions is in active development. It lets you keep your own SDK clients (and the agents running on top of them) within bounds. It's not an admin-level access-control system; it's a way for you to set guardrails on your own credentials. The shape of these options may change as the feature stabilizes.
</Warning>

## What It Is

A **permission policy** is a list of allow and deny rules attached to one of your SDK credentials. You build it up over time: when your code makes a request that isn't already covered by the policy, the SDK pauses and prompts you in your browser to add a rule for that scope. Approving adds an allow rule; denying adds a deny rule. Future requests of the same shape are evaluated against those rules without prompting you again.

For each request, the backend returns one of three outcomes:

* **Allowed**: matches an existing allow rule. Goes through normally.
* **Denied**: matches an existing deny rule. The SDK throws and there's no path to retry.
* **Not yet covered**: no rule matches. The SDK prompts you to add one.

When prompted, you pick a **scope** (typically **Read only** or **Read + Write**) and click Approve or Deny. A single connection can need multiple prompts as your code escalates: the read-only allow rule from the first prompt won't cover a later write call, so the SDK prompts again for Read + Write.

## Why Use It

* **An agent acting on your behalf.** When you hand your SDK credentials to Claude, Cursor, or another AI agent, permissions give you a per-action checkpoint before it does anything irreversible to your Zapier connections.
* **A long-running script.** A cron job or background worker is running with your credentials. Permissions act as a tripwire: if it ever tries to write somewhere it shouldn't, you're notified rather than letting it succeed silently.

## How to Use It

### Step 1: Authenticate with approvals enabled

Run `signup` or `login` with `--use-approvals`:

```bash theme={null}
npx zapier-sdk signup --use-approvals
```

Already have a Zapier account? Use `login` instead:

```bash theme={null}
npx zapier-sdk login --use-approvals
```

Both commands provision an OAuth client credential with an empty policy attached. Every request through that credential will require approval until the policy is built up.

### Step 2: Pick an approval mode

The SDK has two approval modes:

* **`poll`** is for when you're at the keyboard. The SDK opens the approval page in your browser and blocks until you click Approve.
* **`throw`** is for when an agent or server is running things. The SDK throws a `ZapierApprovalError` carrying the approval URL on `err.approvalUrl`. Whoever is running the code surfaces that URL to a human (Slack DM, chat reply, ticket, email), and the human approves out-of-band.

<Tip>
  **You usually don't need to set this.** If `ZAPIER_APPROVAL_MODE` (and the `approvalMode` option) are both unset, the SDK auto-picks based on the environment: `poll` when stdin and stdout are both interactive TTYs, and `throw` everywhere else (agents, servers, CI, anything piped).
</Tip>

To override the auto-detected mode, set the env var:

```bash theme={null}
export ZAPIER_APPROVAL_MODE=throw
```

Or pass `approvalMode` when you create your SDK client. The constructor option wins over the env var, which wins over the auto-detected default.

### Step 3: Run your code

Your existing calls work unchanged. When a call needs approval, the flow depends on the mode.

**Poll mode** keeps the call alive while you approve in the browser:

```mermaid theme={null}
sequenceDiagram
  actor You
  participant Script as Your script
  participant Zapier
  participant Browser

  Script->>Zapier: Request
  Zapier->>Browser: Approval page opens
  Browser->>You: "Allow access to Slack?"
  You->>Browser: Click Approve
  Script->>Zapier: Retries the request
  Zapier->>Script: Returns result
```

**Throw mode** hands the approval URL off to a human and lets the runner retry later:

```mermaid theme={null}
sequenceDiagram
  actor You
  participant Agent
  participant Browser as Approval page

  You->>Agent: "What is on my calendar?"
  Agent->>You: "I need your approval: <approvalUrl>"
  You->>Browser: Open URL, click Approve
  You->>Agent: "Approved, try again"
  Agent->>You: "You have a meeting at 3pm..."
```

In throw mode, your agent only needs to do one thing: catch `ZapierApprovalError` and surface `err.approvalUrl` to whoever is supervising it.

## What It Doesn't Do

* **Not admin-level access control.** Permissions are guardrails on your own credentials, not an org-wide policy system. Other people on your team can't be governed through your policy.
* **Only OAuth Client Credentials.** Permission enforcement applies to SDK clients authenticated via Client Credentials. Clients using other auth methods bypass policies entirely.
* **Tables aren't enrolled yet.** Calls through the SDK's Tables surface aren't gated by approvals today, even when the rest of the connection is.

## Next Steps

* [Quickstart](/sdk/quickstart): install and authenticate before working through this page.
* [Using the CLI](/sdk/using-the-cli): explore and run actions from the terminal.
