https://bouncebox.app
Authentication
BounceBox uses OAuth 2.0 authorization-code flow — no PKCE, no scopes. All API calls sendAuthorization: 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:
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
List mailboxes
GET /api/integrations/zapier/mailboxes
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:
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. 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 anX-BounceBox-Signature header. A subscription auto-deactivates after consecutive delivery failures.
mail.received fires at intake. mail.processed fires when extraction finishes. Payload fields:
Related
- Zapier integration — connect your account, triggers, and actions from the user side.
- Webhooks — per-mailbox webhook output without Zapier.