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

# Zapier API

> REST API reference for the endpoints the BounceBox Zapier integration calls — OAuth, triggers, actions, and webhook subscriptions.

This is the REST API the BounceBox Zapier integration calls. It is documented for reviewers verifying the integration and for integrators building against the same surface.

Base URL: `https://bouncebox.app`

## Authentication

BounceBox uses OAuth 2.0 authorization-code flow — no PKCE, no scopes. All API calls send `Authorization: Bearer <access_token>`. Only token hashes are stored server-side.

### Authorize

`GET /api/integrations/zapier/oauth/authorize`

Query parameters: `client_id`, `redirect_uri`, `response_type=code`, `state`. Redirects to the dashboard login, then 302s back to `redirect_uri` with a `code` (10-minute TTL) and `state`.

### Token

`POST /api/integrations/zapier/oauth/token`

JSON or form-encoded body: `grant_type=authorization_code`, `code`, `redirect_uri`, `client_id`, `client_secret`.

Response:

```json theme={null}
{
  "access_token": "...",
  "token_type": "bearer",
  "expires_in": 3600,
  "refresh_token": "..."
}
```

### Refresh

`POST /api/integrations/zapier/oauth/refresh`

Body: `grant_type=refresh_token`, `refresh_token`, `client_id`, `client_secret`. Same response shape as the token endpoint. Rotates both tokens — the old pair stops working.

### Revoke

`POST /api/integrations/zapier/oauth/revoke`

Client-authenticated. Revokes the token row.

An invalid or expired bearer token returns `401` with `{"error": "invalid_token"}`.

## Endpoints

All endpoints are scoped to the workspace the token was issued for.

### Connection test

`GET /api/integrations/zapier/me`

```json theme={null}
{
  "user_id": "...",
  "email": "you@example.com",
  "workspace_id": "...",
  "workspace_name": "Acme"
}
```

### List mailboxes

`GET /api/integrations/zapier/mailboxes`

```json theme={null}
{ "mailboxes": [{ "id": "...", "address": "orders@in.bouncebox.app", "label": "Orders" }] }
```

Source for the mailbox dropdown in Zap steps.

### Received mail samples

`GET /api/integrations/zapier/triggers/received?mailbox_id&limit`

`limit` accepts 1–10. Returns `{ "emails": [...] }` — the newest received emails, each in the `mail.received` payload shape below. Returns `404` when `mailbox_id` belongs to another workspace.

### Processed mail samples

`GET /api/integrations/zapier/triggers/processed?mailbox_id&limit`

Returns `{ "emails": [...] }` — newest emails joined to their latest extraction result, each in the `mail.processed` payload shape below.

### Send email

`POST /api/integrations/zapier/emails`

Body:

```json theme={null}
{
  "mailbox_id": "required",
  "from": "optional",
  "subject": "optional",
  "text": "optional",
  "html": "optional",
  "attachments": [
    { "filename": "required", "contentType": "optional", "base64": "required" }
  ]
}
```

Provide `text` or `html` or at least one attachment. Returns `202` with `{ "email_id", "mailbox_id", "status": "processing" }` — the email enters the normal pipeline. Errors: `400` missing `mailbox_id` or empty content, `404` foreign mailbox.

### Email actions

`POST /api/integrations/zapier/actions/emails/{id}`

Body: `{ "action": "approve" | "reprocess" | "skip", "result_id": "optional", "expected_revision": "optional" }`.

Returns `{ "ok": true, "emailId": "...", "action": "...", ... }` — approve adds `resultId` and `revision`. Errors: `400` unknown action, `404` email or result not found, `409` conflict (for example a stale revision), `503` scheduling failed.

### Subscribe to webhooks

`POST /api/integrations/zapier/webhooks/subscribe`

Body: `{ "webhook_url": "required", "event_type": "mail.received | mail.processed", "mailbox_id": "optional" }`.

`webhook_url` must be a **public HTTPS** URL — the same rule as [mailbox webhooks](https://docs.bouncebox.app/configuration/webhooks.md). Plain HTTP, localhost, and private network addresses are rejected with `400`.

Returns `201` with `{ "subscription_id": "..." }`. Re-subscribing an identical subscription returns `200` — the call is idempotent on workspace + event + URL + mailbox.

### Unsubscribe

`DELETE /api/integrations/zapier/webhooks/{id}`

Returns `204` always — idempotent.

## Webhook deliveries

Deliveries POST a JSON payload to the subscribed URL with an `X-BounceBox-Signature` header. A subscription auto-deactivates after consecutive delivery failures.

`mail.received` fires at intake. `mail.processed` fires when extraction finishes. Payload fields:

| Field | Event | Notes |
| - | - | - |
| `id` | both | Unique delivery item id |
| `email_id`, `mailbox_id` | both | |
| `mailbox_address`, `mailbox_label`, `schema_template` | both | |
| `from`, `to`, `subject`, `received_at`, `status` | both | `to` is an array |
| `attachments` | both | Filename, contentType, size |
| `result_id`, `result_revision` | `mail.processed` | |
| `data` | `mail.processed` | Extracted result — shape follows the mailbox's extraction template |
| `attachments[].url` | `mail.processed` | Signed download URL, valid 7 days |

## Related

* [Zapier integration](https://docs.bouncebox.app/integrations/zapier.md) — connect your account, triggers, and actions from the user side.
* [Webhooks](https://docs.bouncebox.app/configuration/webhooks.md) — per-mailbox webhook output without Zapier.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.