s46.apiv1

Errors & status codes

Stable JSON error envelope and code catalog.

Every JSON failure uses one envelope. Branch on HTTP status plus error.code — never parse message; it is human-readable and may change.

The envelope

{
  "error": {
    "code": "invalid_request",
    "message": "invalid request"
  }
}

Some auth-bootstrap errors include extra fields (for example an auth object pointing at the login routes), but clients should always branch on status + code.

Code catalog

Grouped by status class. Every code below is stable and safe to switch on.

4xx — request & auth

HTTPCodeWhen it fires
400invalid_requestMalformed path/query/body value, or an unsupported state.
400bad_jsonRequest body is not valid JSON.
401authenticate_firstBrowser/device approval needs an authenticated magic-link session first.
401unauthorizedMissing, expired, revoked, or invalid bearer / cookie / worker credential.
403not_invitedEmail is not currently invited, or the invitation was revoked.
403forbiddenAuthenticated user lacks the owner/admin role, or the action is disallowed.
403model_not_allowedRequested model is not certified/allowed for the caller's team.
404not_foundTarget does not exist or is not visible to the credential.
405method_not_allowedRoute exists but the HTTP method is unsupported.
409conflictResource conflict or duplicate state.
409idempotency_conflictIdempotency-Key reused with different parameters.
410expiredLogin, magic link, or token expired.
412precondition_failedIf-Match revision / ETag is stale.
428authorization_pendingPolling target is not ready yet — see contexts below .
428precondition_requiredA required header such as Idempotency-Key is missing.
429rate_limitedRequest or stream rate limit exceeded.
429capacity_limitedCapacity exists but is temporarily saturated.

5xx — service & availability

HTTPCodeWhen it fires
503email_unavailableInvite or magic-link email delivery is not configured or failed.
503model_unavailableNo ready upstream/local model worker is available.
503service_unavailableControl service is unavailable.
503rate_limiter_unavailableRate-limiter backend is unavailable.
500internal_errorUnhandled server-side failure.

authorization_pending contexts

This one code is shared by several polling-style endpoints — the caller should retry later. Branch on endpoint context, not on the assumption that it always means device login:

  • Device login waiting for magic-link approval.
  • Session attach or stream waiting for a queued remote session.
  • Worker job leasing when no compatible work is available yet, or the worker cannot lease.

Client guidance

SituationDo
authorization_pendingRetry after the endpoint-specific polling interval, or use exponential backoff.
401 unauthorizedRefresh credentials only if you hold a valid refresh token/cookie; otherwise restart login.
403 forbidden / model_not_allowedDo not retry blindly — change credentials, membership, or model policy first.
retrying mutationsPreserve and reuse the same Idempotency-Key for safe retries.
error.messageDo not parse it — it is human-readable and may change. Use code.

On this page