Errors
One envelope, the status mapping, and the two refusals that are not what they look like.
Every refusal on this API has the same body:
{
"error": {
"type": "invalid_request_error",
"code": "approve_required",
"message": "…",
"param": "publish.approve",
"request_id": "req_…"
}
}Switch on type to decide whether to retry, fix the request, or escalate; code is the specific reason within that
family. param names the offending field when there is one, and is omitted rather than sent empty.
request_id matches the x-string-request-id response header and our log line, so quote it when you ask us about a
request.
Status codes
| Status | Condition | Retriable |
|---|---|---|
400 | Invalid argument, out of range | Not until you change the request |
401 | Bad or missing API key | No |
404 | Unknown build | No |
409 | Already exists, failed precondition, aborted | After the build's state changes |
413 | Body over 1 MiB | No |
429 | Rate limited — honour Retry-After | Yes |
499 | The request was already cancelled upstream | n/a |
501 | Recognised but not served (see below) | No |
503 | Our key store or core is unreachable | Yes |
504 | Upstream timeout | Yes |
500 | Anything else, with a deliberately generic message | Maybe |
Retry-After on a 429 is always present and never zero.
Three answers that are not what they look like
409, not 400, for a state conflict
Input sent to a build that has finished, or a gate answered after it stopped being pending, is a 409. Your request
is already correct — the build moved. A 400 would send you to re-read JSON that has nothing wrong with it. Resolve
it by re-reading the build's state, not by editing your body.
501, not 400, for an unserved mode
mode: "autonomous", mode: "fast" and publication.policy: "auto" return 501 with codes mode_not_supported
and publication_policy_not_supported. The request is well formed and names a mode this API documents; the missing
capability is ours. See Limits.
503, not 401, when our key store is down
An unreachable key store answers 503 precisely so that you do not rotate a working key during our incident.
There is no 403
A build owned by another organization returns a byte-identical 404 to an unknown id — same status, same code,
same message, built from the id you supplied. Nothing inspects the id, the organization, or the message to choose
between them.
That is deliberate: a distinguishable answer would be an oracle, letting a caller walk build ids and learn which ones are real. Do not write client code that tries to tell the two apart, because nothing distinguishes them.