Safeguards
Errors
OTPRelay uses conventional HTTP status codes and returns a consistent JSON error envelope so you can branch on a stable type and code rather than parsing messages.
OTPRelay follows standard HTTP conventions: 2xx indicates success, 4xx indicates a problem with the request (a bad parameter, a missing key, a closed verification), and 5xxindicates an error on OTPRelay's side. Every failed request returns the same JSON shape, so you can handle errors uniformly across endpoints.
One case is deliberately not an HTTP error: submitting a wrong code to Check a verification returns 200 OK with verified: false. See the error codes table below.
The error object
Errors are wrapped in a top-level error object. Always branch on type and code - the message is for humans and may change.
typestringrequired- The broad category of the error, e.g.
invalid_request_error. See Error types. codestringrequired- A stable, machine-readable identifier for the specific failure, e.g.
invalid_phone_number. Branch on this in code. See Error codes. messagestringrequired- A short, human-readable description of what went wrong. For logs and debugging - do not match on its text.
paramstringoptional- Present when the error relates to a specific request field. Names the offending parameter, e.g.
to. doc_urlstringoptional- Present when there is relevant documentation. A link to the page describing this error and how to resolve it.
Error types
The type field groups errors into a handful of categories. Use it for coarse-grained handling - for example, retrying on api_error while surfacing invalid_request_error to the caller.
| type | when |
|---|---|
invalid_request_error | The request was malformed: a parameter is missing, the wrong type, or otherwise invalid. Fix the request before retrying. |
authentication_error | The API key is missing, malformed or expired. Returns 401. See Authentication. |
rate_limit_error | You hit a built-in limit - too many concurrent requests, or the per-verification send or check ceiling. Returns 429. See Rate limits & fraud. |
delivery_error | The code could not be delivered - the destination is blocked by Fraud Guard, or the country isn't enabled. |
api_error | Something went wrong on OTPRelay's side. Returns a 5xx status. These are rare and safe to retry with backoff. |
Error codes
The code field is the value to branch on. The table below lists every code, its HTTP status, and what it means.
| code | HTTP | meaning |
|---|---|---|
invalid_phone_number | 400 | to is not a valid E.164 phone number. |
invalid_parameter | 400 | A parameter is present but malformed or out of range. |
missing_parameter | 400 | A required field is missing from the request. |
authentication_failed | 401 | The API key is bad, missing or expired. See Authentication. |
verification_not_found | 404 | No open verification matches the verification_id or to - it never existed or is already closed. |
incorrect_code | 200 | The submitted code is wrong. Returned in the body - the HTTP status stays 200 and the verification stays pending. |
max_check_attempts | 429 | More than 5 checks on this verification. It is now closed (max_attempts_reached). |
max_send_attempts | 429 | More than 5 sends to this number on a single verification. |
too_many_requests | 429 | A concurrency or rate limit was hit for this number. See Rate limits & fraud. |
delivery_blocked | 402 | Fraud Guard blocked the destination. See Rate limits & fraud. |
country_not_supported | 400 | The destination is outside OTPRelay's enabled countries. See GCC compliance & coverage. |
incorrect_code is not an HTTP error
200 OK - read verified: false in the body and let the user try again until the verification is approved, expires, or hits its check limit. See Check a verification.For the full request and response shapes that produce these errors, see Send a verification and Check a verification. Anything still undecided - including idempotency semantics and the programmable rate-limit shape - is still being finalized.