Skip to main content
Failures on the agent surface are explicit and predictable. Most are enforced boundaries — a scope you weren’t granted, a quota you’ve used up, a blast that only a human can send — not transient bugs. This page lists every failure mode and the right way to handle it.

How errors surface

  • Via MCP: a failed tool call comes back as a ToolError whose message is the Rails error text, verbatim (e.g. Access token is missing the required scope: contacts:manage). Your agent reads that message and should act on it, not retry blindly.
  • Via REST (direct): you get the HTTP status plus a JSON body { "error": "<message>" }.
The MCP server surfaces Rails’ own reason unchanged. Only when Rails returns an empty/generic auth body does the server append a hint that the scope or X-Sapot-Account-Id may be wrong — so a real business-rule refusal is never mislabeled as an auth problem.

Authentication & scope errors (401)

All four are returned as HTTP 401 and are not retryable — the same call will fail identically until you fix the token, its scopes, or the account id.
Never retry a scope or boundary refusal. If a tool reports a missing scope, tell the user which scope to add rather than looping. See Authentication & Scopes.

Business-rule refusals (403 / 422)

Some calls authenticate and carry the right scope but are refused by a product rule. The Rails message surfaces verbatim so you know why. Common cases:
  • Editing a non-draft campaign — an agent key may only edit its own draft campaigns; touching a scheduled/sending campaign is refused. Draft a new one or ask the human to manage the live campaign from the dashboard.
  • WhatsApp template CRUD on a non-eligible inbox — create/update/delete require a WhatsApp Cloud inbox and an admin-level token.
  • Validation errors (422) — a malformed payload (missing required field, bad enum value). Fix the arguments and resend.
These are not retryable as-is: change the request, don’t repeat it.

Quota exceeded (429)

Agent action quota exceeded for the current billing period (HTTP 429) means your account has used up its plan’s MCP-action allowance for the current billing period.
How the quota works:
  • It is a per-plan, per-billing-period allowance on total agent actions.
  • It resets automatically at the next billing-period renewal (on Stripe renewal, and on calendar rollover).
  • Upgrading to a higher plan raises the cap and clears the block once the higher cap sits above current usage. A downgrade or same-tier change does NOT clear it — you still wait for the reset.
  • Accounts with no finite cap (unlimited plans) never hit this — the quota is dormant until a plan sets a finite agent_actions limit.
When you see a 429, stop and tell the user — back off rather than hammering the endpoint.

What counts against your usage

Metering is precise: only work that actually happened is charged.
  • Only allowed + successful (2xx) calls count — against both your key’s usage and the account quota.
  • Refused or errored calls consume nothing: 401 (auth/scope), 403 (business rule), 404 (not found), 422 (validation), 429 (over quota), and 500 (server error) are all free.
  • Per-key usage is shown as the Calls column in Settings → API & Agents.
  • The account-level counter is claimed atomically, so concurrent bursts can never push usage past the cap.
This means a scope-denied or failed request never inflates your bill or your key’s call count — you’re only ever metered for real, successful actions.

Asynchronous caveats

A few operations complete out of band. A “nothing happened yet” result here is expected, not a failure:
  • WhatsApp templatescreate_whatsapp_template / update_whatsapp_template return status PENDING. Meta approves out of band and approval cannot be forced via the API. Poll list_whatsapp_templates to see the status change.
  • Template syncsync_whatsapp_templates runs in the background and returns { message: "..." } immediately. Call list_whatsapp_templates afterwards to see the refreshed set.
  • Campaign drafts never auto-send — a campaign drafted or edited by an agent key is forced into a non-sending draft state, no matter how it’s scheduled. Only a human clicking Send in the dashboard fires the blast. “It didn’t send” is the enforced boundary, not a bug — see Campaigns & Blasts.

Retry guidance

Rate limits (planned)

There is no per-minute rate limit today — the per-plan quota above is the only cap on total usage. A per-minute throttle is a planned addition; when it ships it will return 429 and follow the same back-off guidance.