How errors surface
- Via MCP: a failed tool call comes back as a
ToolErrorwhose 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.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.
Quota exceeded (429)
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_actionslimit.
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), and500(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.
Asynchronous caveats
A few operations complete out of band. A “nothing happened yet” result here is expected, not a failure:- WhatsApp templates —
create_whatsapp_template/update_whatsapp_templatereturn statusPENDING. Meta approves out of band and approval cannot be forced via the API. Polllist_whatsapp_templatesto see the status change. - Template sync —
sync_whatsapp_templatesruns in the background and returns{ message: "..." }immediately. Calllist_whatsapp_templatesafterwards 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
draftstate, 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.
