Skip to content

Errors

The shape

Every error returns the same JSON, with no stack traces, SQL, or file paths:

{ "error": { "code": "authenticate_user.invalid_credentials", "message": "authenticate_user.invalid_credentials" } }

The code is a stable translation key, not localized text. Your client maps it to a message in the user's language at render time, so error copy lives on your side and never changes under you.

Status codes

  • 400 Bad Request: malformed input (invalid email, bad UUID, unknown query value).
  • 401 Unauthorized: missing or invalid key or token.
  • 402 Payment Required: the wallet has no balance to reserve the job. Distinct from 403 so you can prompt a top-up rather than a permission fix.
  • 403 Forbidden: the key is missing the required scope or check.
  • 404 Not Found: no such resource for your account (a UUID owned by someone else looks identical to a missing one).
  • 408 Request Timeout: the request exceeded the server's processing budget (request.timeout); safe to retry.
  • 409 Conflict: for example an idempotency key reused with a different body.
  • 429 Too Many Requests: rate limit exceeded. The response carries Retry-After.

No enumeration

Authentication failures return the same error for an unknown email and a wrong password, so responses never reveal whether an account exists.