Core Concepts

Errors

Every error response shares one shape, regardless of endpoint.

{
  "error": {
    "message": "Human-readable description",
    "code": "MACHINE_READABLE_CODE",
    "details": { }
  }
}

details is only present on some validation errors (for example, OTP verification includes attemptsRemaining). Success responses are always shaped as { "data": ... }, optionally with a sibling meta key.

Status codes

HTTP statusCodeMeaning
401UNAUTHENTICATEDMissing, malformed, or invalid credentials — bearer token or application credential triple
403FORBIDDENCredentials are valid but not permitted for this action, e.g. a suspended application
404NOT_FOUNDResource doesn't exist, or exists but isn't owned by the caller
409CONFLICTThe request can't be completed given current state — e.g. deleting a project that still has applications
422VALIDATION_ERRORRequest body or parameters failed validation
429RATE_LIMITEDSee Rate Limits
500INTERNAL_ERRORUnhandled server-side failure — safe to retry, worth reporting if persistent
501NOT_IMPLEMENTEDReserved for endpoints not yet built

Why 404 instead of 403 for ownership

Every console-scoped resource lookup (a project, application, webhook, or OTP request that belongs to someone else) returns 404 rather than 403. This is deliberate: a 403 confirms the resource exists, which is itself information an attacker enumerating IDs shouldn't get for free.

Common causes

SymptomLikely cause
401 on /v1/otp/sendClient ID, Client Secret, and API Key must all belong to the same application — check for a copy-paste mismatch across environments (test vs live)
422 on /v1/otp/sendPhone number doesn't match the expected virtual format, e.g. +999 482 918 102
422 on /v1/otp/verifyOTP has expired (5-minute TTL) or the code is wrong — check attemptsRemaining in the response
409 on deleting a projectThe project still has applications — delete or move them first