Errors

How the OpenRelay API reports errors — status codes and the JSON error body.

The API uses conventional HTTP status codes. 2xx means success. 4xx means the request was rejected (and usually shouldn't be retried unchanged). 5xx means something went wrong on our side.

Error body

Every error response has a JSON body with a human-readable error message and an optional machine-readable code:

{
  "error": "cluster not found",
  "code": "not_found"
}

Always branch on the HTTP status code first; treat code as a stable hint and error as a message for logs and humans.

Status codes

StatusMeaningWhat to do
200OKSuccess.
400Bad RequestMalformed JSON or invalid parameters. Fix the request.
401UnauthorizedMissing, invalid, or expired API key. Check the Authorization header.
403ForbiddenThe key is valid but lacks the scope, or targets another org.
404Not FoundThe resource doesn't exist (or isn't visible to your org).
409ConflictThe request conflicts with current state (e.g. a name clash, or an action invalid for the resource's status).
422UnprocessableThe request is well-formed but semantically invalid.
429Too Many RequestsYou're being rate limited. Back off and retry.
5xxServer ErrorA transient problem on our end. Retry with backoff.

Retrying

Retry safely

Retry only idempotent requests (GET, and creates you can safely repeat) and only on 429 and 5xx. Use exponential backoff with jitter, and respect the Retry-After header on 429 responses when present.

# Example: retry a GET up to 5 times with backoff
for i in 1 2 4 8 16; do
  if curl -fsS https://api.openrelay.inc/v1/vms/$VM_ID \
      -H "Authorization: Bearer $OPENRELAY_API_KEY"; then
    break
  fi
  sleep "$i"
done

Diagnosing failures

For resources that can land in a failed or stuck state (VMs, clusters), the resource body carries a statusReason field with a human-readable cause — read it before retrying a create.

On this page