Documentation

Errors

AdminUpdated Sep 20, 2026

Errors

Restore Hub uses standard HTTP status codes and a single, predictable error envelope. Every error response is JSON; even rate-limit and infrastructure errors stay in the same shape.

Response shape

{
  "error": "Human-readable summary of what went wrong.",
  "details": {
    // Optional. Field-level details when relevant
    // (e.g. zod validation issues, the missing scope, etc.)
  }
}

The error string is always present. details is provided for:

  • Validation errors (Zod issues, malformed JSON)

  • Scope failures (the required scope is named)

  • Rate-limit responses (when retry-after info applies)

  • Some plan-limit responses (current usage, max allowed)

HTTP status codes

Code

Meaning

What to do

200

OK

Success. Read the response body.

201

Created

Resource was created. Body holds the new entity.

204

No Content

Operation succeeded; no body. Common after deletes.

400

Bad Request

Validation or malformed payload. Inspect details.

401

Unauthorized

Missing/invalid/revoked API key. Re-mint or re-send.

403

Forbidden

Authenticated but lacking scope or ownership. See details.requiredScope.

404

Not Found

Resource doesn't exist or your key can't see it. Treat as not-yours.

409

Conflict

Resource already exists or competing operation in progress. Re-fetch state.

422

Unprocessable Entity

Plan limit or business-rule violation. Read error for the rule.

429

Too Many Requests

Rate limited. See Rate Limits for backoff.

500

Internal Server Error

Our fault. Retry with exponential backoff; report if persistent.

502 / 503

Bad Gateway / Unavailable

Transient infra issue. Same retry strategy as 500.

Authentication errors

401 Unauthorized

{ "error": "Missing or invalid API key." }

Causes: no Authorization header, wrong format, key revoked, or key from a deleted account.

403 Forbidden — missing scope

{
  "error": "Missing required scope: backups:restore",
  "requiredScope": "backups:restore",
  "yourScopes": ["servers:read", "backups:read"]
}

Mint a new key with the right scope (or edit the existing one). See all scopes.

403 Forbidden — not your resource

{ "error": "You do not own this server." }

You authenticated correctly, but the resource you targeted isn't yours. Could also indicate a team-membership issue. Verify the resource ID belongs to your account.

Validation errors

{
  "error": "Invalid request body.",
  "details": {
    "issues": [
      { "path": ["name"], "message": "Required" },
      { "path": ["category"], "message": "Invalid enum value. Expected 'gaming' | 'community' | ..." }
    ]
  }
}

Zod-style issue list. Each issue has a path (where the bad value lives) and a human message.

Rate-limit errors

{
  "error": "Rate limit exceeded.",
  "retryAfterSeconds": 12
}

Plus a standard Retry-After header. Full strategy on Rate Limits.

Recommended handling for agents & scripts

  • 401 → re-prompt the user / fail fast. Don't retry blindly.

  • 403 → surface the missing scope to the user. Don't try to circumvent.

  • 404 → treat the resource as not-yours. Don't crawl.

  • 409 → re-fetch and reconcile state.

  • 422 → respect the plan rule. Tell the user to upgrade if they want this.

  • 429 → exponential backoff, honor Retry-After.

  • 5xx → retry with jitter, max 3 attempts, then fail.

Was this page helpful?