Error codes
Errors a machine can act on.
All billing failures are JSON-RPC errors over HTTP 200 — that is what MCP clients surface to their model and user. Transport-level 401s would push OAuth-capable clients into a discovery flow this server doesn't offer; in-band errors keep every client on the happy path.
Tollgate codes
HTTP-mnemonic (401 / 402 / 429), and deliberately outside both the JSON-RPC reserved range (-32768…-32000) and the codes MCP itself uses — a Tollgate error can never be mistaken for a protocol one.
| code | meaning | error.data | what your agent should do |
|---|---|---|---|
| -31401 | API key missing, unknown or revoked | reason, signup_url | Send the user to signup_url; free tier needs no card. |
| -31402 | Out of credits | reason, credits_remaining, checkout_url, pricing | Open checkout_url. Discovery still works while at zero. |
| -31429 | Rate limit (120 req/min per key) | retry_after_seconds | Back off and retry; budget batch jobs to ~2 calls/sec. |
Standard codes you'll also meet
| code | raised when |
|---|---|
| -32700 | body is not valid JSON |
| -32600 | JSON-RPC batch (unsupported — one message, one charge) or not a request |
| -32601 | unknown method (e.g. prompts/list — this server has no prompts) |
| -32602 | unknown tool name or malformed params |
| -32002 | unknown resource URI on resources/read (the spec's own code) |
| -32603 | our bug, logged server-side; details deliberately not leaked |
Tool-level failures
Fixable argument mistakes (bad enum value, one model instead of two) come back as a normal result with
isError: true and a plain-text explanation — per spec, so the calling model sees the text and
can correct itself without burning the request loop.
Billing metadata on success
{
"content": […],
"structuredContent": { … },
"_meta": {
"tollgate/credits": { "charged": 1, "remaining": 186 }
}
}
Agents should never be surprised by their balance — it rides along on every charged result.