02 · CONCEPTS
Errors
Every non-2xx response has exactly one shape. Codes tell your agent what to do next — most of them are not “try again.”
Error envelope
{
"error": {
"code": "insufficient_credits",
"message": "available credits below the maximum cost of this call",
"request_id": "…", // when a request was created
"details": { } // code-specific context
}
}1
Codes & the retry matrix
| Code | HTTP | Retry? | What to do |
|---|---|---|---|
| unauthorized | 401 | no | Missing or revoked key. Create one in the console. |
| forbidden | 403 | no | Key lacks the required scope, or the workspace needs review for external actions. |
| confirmation_required | 403 | after approval | A human must approve this action in the console. Get a fresh preview, have them approve, retry with the token. |
| insufficient_credits | 402 | after top-up | Top up in the console. Quote tokens survive this — no need to re-quote. |
| rate_limited | 429 | yes, backoff | 300 requests/min per key. Back off and retry. |
| idempotency_conflict | 409 | no | Same Idempotency-Key, different parameters. Use a new key for a new request. |
| invalid_request | 400 | no | Schema/validation failure — the message says which field. |
| suppressed_recipient | 422 | no | Recipient is suppressed. This is permanent and by design. |
| not_found | 404 | no | Wrong id, or it belongs to another workspace. |
| operation_unknown_state | 409 | poll, don't retry | External outcome is ambiguous and being reconciled. Poll the request/operation; never blind-retry a purchase, launch or reply. |
| reply_already_sent | 409 | no | This inbound reply already has an answer in flight or sent. One reply per inbound message; wait for their next message. |
| reply_content_unavailable | 409 | no | The provider message this reply would answer is not held, so it cannot be threaded. Read it with get_reply first. |
| reply_send_disabled | 403 | no | In-thread reply sending is switched off for this deployment or workspace. |
| mailbox_unavailable | 409 | no | The mailbox that received this reply is no longer an active sending asset in your workspace. Layrcake never substitutes another sender. |
| provider_unavailable | 503 | yes, later | Every route exhausted. Nothing was charged. Retry with the same Idempotency-Key. |
| internal | 500 | yes, later | Our fault. The request_id helps support trace it. |
🔁 Retrying safely: reuse the same Idempotency-Key and you can never be double-charged — a completed request replays its original result; an in-flight one returns 202 in_progress.