Skip to main content

The response envelope

Every response has the same outer shape, success or failure, so you never have to guess whether a 200 actually worked.
Check success first, then read data. The error string is written for a person. Show it or log it, but don’t parse it, because we reword messages when a clearer one comes along. Branch on the HTTP status instead. A few errors also carry a machine-readable code. For example, a closed account answers with "code": "ACCOUNT_BANNED". Two endpoints don’t return JSON when they succeed: invoice PDFs and ticket attachment downloads send the file itself. Their errors still use the envelope.

Status codes

The 404 behaviour is worth remembering. If you ask about someone else’s service, you get “not found”, not “forbidden”. Otherwise the API would let anyone check which service IDs exist.
403 covers more than scopes, so read the error message before you reach for a new token. A suspended server won’t start working with a wider token. It starts working once the invoice is paid.

Rate limits

Most token endpoints have no per-request limit today. A handful do, and they answer 429 once you go over:
Windows are fixed, not sliding. When you get a 429, wait out the rest of the minute and try again. Don’t hammer the endpoint. No published limit doesn’t mean unlimited. If you’re planning something high-volume, like polling thousands of servers every few seconds, talk to us first rather than finding the edge by hitting it. List endpoints read from our database, not the hypervisor, so one paged GET /v1/cloud is far cheaper than a status call per machine.

Failed authentication and IP blocks

Repeated bad credentials from one IP get that IP blocked automatically. Ten failures inside 15 minutes trigger the first block, and each repeat lasts longer: While blocked, every request from that IP gets a 403 with a Retry-After header, in seconds:
Only failures that look like guessing count: an API token that doesn’t match anything, or one that’s the wrong shape. A revoked or expired token fails with its own message and doesn’t count. That’s nearly always a stale config, not an attack. A successful request with a valid token clears your count.
Never retry a 401 in a loop. The credential won’t fix itself, and a tight retry loop with a mistyped token is the quickest way to get your CI runners’ shared IP blocked for a week.

Handling errors well

A good client:
  • Checks success, then branches on the status code.
  • Treats 401 as “stop and fix the credential”, never “retry”.
  • Retries 429, 502 and 503 with backoff, and caps the number of attempts.
  • Doesn’t retry 409 blindly. Re-read the resource’s state first, because something else has changed it.
  • Logs the error string, since it’s the fastest way for us to help when you open a ticket.