Errors
Errors are RFC 9457 problem documents served as
application/problem+json:
{
"type": "https://braesystems.com/docs/errors/server-busy",
"title": "Server busy",
"status": 409,
"detail": "A re-image is in progress. Rebooting now would leave the server without a working OS."
}Branch on type. It is a stable identifier; title and detail are prose and may be reworded.
Catalogue
type suffix | Status | Meaning and what to do |
|---|---|---|
unauthorized | 401 | Missing, malformed, revoked, or unknown API key. Check the Authorization: Bearer bs_live_… header. |
forbidden | 403 | Authenticated, but not permitted. |
not-found | 404 | No such resource in your account. See the note below. |
invalid-request | 400 | The body or parameters failed validation. detail names the field. |
invalid-ssh-key | 400 | The public key could not be parsed. |
duplicate-ssh-key | 409 | A key with that fingerprint is already on the account. |
server-busy | 409 | Another operation is already running on the server. Retry once it settles. |
server-not-ready | 409 | The server’s state does not allow the operation. |
unknown-image | 400 | No such image slug. See GET /api/v1/images. |
rate-limited | 429 | Too many requests. Back off and retry. |
internal | 500 | Something broke on our side. Retry; if it persists, contact us with the response. |
Why 404 and not 403
A resource belonging to another account returns 404, exactly as a resource that does not exist
does. This is deliberate: distinguishing the two would confirm that a given id exists somewhere,
letting a caller enumerate other customers’ server and key ids by guessing.
For the same reason, passing an ssh_key_ids value that belongs to another account returns
400 invalid-request rather than 404.
Retrying
409 and 429 are worth retrying — the first once the current operation finishes, the second after a
backoff. 500 is worth one or two retries.
400, 401, 403, and 404 will not change on retry; the request itself needs fixing.
Failed operations are not errors
A reboot or re-image that fails still returns 202 at request time — the request was accepted. The
failure surfaces on the action:
{
"data": {
"id": "6b5a4c3d-2e1f-4a9b-8c7d-6e5f4a3b2c1d",
"kind": "reboot",
"status": "failed",
"error": "Server never left power state On after 10.0 minutes; the restart appears to have been ignored.",
"simulated": false
}
}Always check status when polling, not just the HTTP code.