Every failure is an RFC 9457 problem document, served as application/problem+json.
Branch on code
code is the stable field. title and detail are human prose and may be reworded at any time without a version bump — never match on them. type is a stable documentation URI and is also safe.
Every code
tool_not_found and tool_disabled look similar and mean opposite things: one says delete this from your integration, the other says try again in a minute. That distinction is why they are separate codes.
Validation errors name the field
Surface fields to whoever supplied the input — it maps one-to-one onto the tool’s documented inputs.
request_id
Every response carries one, in three places: the body, the x-request-id header, and our server logs. Quoting it turns “it failed once around 14:20” into a query.
You can supply your own by sending an x-request-id header, and we will echo it — handy for correlating with your own tracing.
Nothing costs credits when it fails
Credits are reserved on entry and refunded on every 4xx and 5xx. This includes the one-credit floor, so a broken integration in a retry loop cannot drain your allowance.
MCP
MCP has no HTTP status to carry, so tool failures come back as an MCP error result with the same code vocabulary in the text:
Parse the prefix up to the first colon.
MCP adds two codes of its own, both about the spending confirmation: declined_by_user (you declined the prompt — nothing ran, nothing was charged) and confirmation_required (the client can’t show a prompt and the call cost more than 50 credits, so it was refused).