> For the complete documentation index, see [llms.txt](https://docs.sms4sats.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sms4sats.com/api-reference/errors.md).

# Errors, Limits & Retries

Handle sms4sats API v2 errors, rate limits, authentication failures, and safe retries.

## Error shape

```json
{
  "error": "UNAVAILABLE",
  "message": "No numbers available",
  "requestId": "<request-id>"
}
```

Application errors normally use this shape. Rate-limit middleware may return a plain `429` body instead, so clients must branch on HTTP status before parsing an application error. Include `requestId` when present and contacting support. Messages for server-side `5xx` errors are intentionally generic.

## Common HTTP responses

| HTTP  | Code examples                                                                                                                                                                                                                                                                  | Meaning / action                                                                            |
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- |
| `400` | `INVALID_REQUEST`, `VALIDATION_ERROR`, `INVALID_INPUT`, `INVALID_COUNTRY`, `INVALID_DURATION`, `IDEMPOTENCY_KEY_REQUIRED`, `INVALID_IDEMPOTENCY_KEY`, `MISSING_SITE`, `INVALID_SITE`, `INVALID_REFUND_INVOICE`, `REFUND_INVOICE_EXPIRES_TOO_SOON`, `PROVIDER_REJECTED`         | Correct the request; do not retry unchanged                                                 |
| `401` | `ORDER_TOKEN_REQUIRED`, `EMAIL_ORDER_TOKEN_REQUIRED`, `MISSING_L402_AUTH`, `INVALID_L402_AUTH`, `INVALID_PREIMAGE`, `INVALID_MACAROON`, `EXPIRED_MACAROON`                                                                                                                     | Supply a valid credential/payment proof                                                     |
| `403` | `INVALID_ORDER_TOKEN`, `EMAIL_ORDER_TOKEN_INVALID`, `CORS_NOT_ALLOWED`                                                                                                                                                                                                         | Bearer order capability is invalid, or the browser origin is not allowed                    |
| `404` | `ORDER_NOT_FOUND`, `EMAIL_ORDER_NOT_FOUND`, `NOT_FOUND`                                                                                                                                                                                                                        | Verify API family and order ID                                                              |
| `409` | `UNAVAILABLE`, `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_IN_PROGRESS`, `ORDER_NOT_PAID`, `CANCEL_NOT_AVAILABLE_YET`, `CANCEL_NOT_SUPPORTED`, `ORDER_NOT_CANCELLABLE`, `RENTAL_NOT_CANCELLABLE`, `EMAIL_DOMAIN_UNAVAILABLE`, `EMAIL_ALREADY_RECEIVED`, `EMAIL_REORDER_NOT_AVAILABLE` | Read the code; refresh state or choose new inventory as appropriate                         |
| `429` | rate limit                                                                                                                                                                                                                                                                     | Honor rate-limit headers; retry with backoff and jitter                                     |
| `500` | `INTERNAL_ERROR`                                                                                                                                                                                                                                                               | Unexpected server failure; preserve `requestId`, avoid duplicate creation, and retry safely |
| `503` | `PROVIDER_UNAVAILABLE`, `PROVIDER_CANCEL_FAILED`, `PAYMENT_RELEASE_FAILED`, `LNBITS_CANCEL_FAILED`, `REFUND_FAILED`, `INVOICE_RECONCILIATION_REQUIRED`, `INVOICE_HASH_MISMATCH`                                                                                                | Temporary dependency/reconciliation condition; do not assume the order failed               |

## Retry policy

### Safe to retry

* Catalog and quote requests.
* Poll requests using the same credential.
* A bearer-token SMS/rental creation request using the **same body and same idempotency key**.
* A `429` or transient `5xx` after waiting with exponential backoff and jitter, only when the operation is read-only or idempotent.

### Never retry blindly

* Creation with a new idempotency key after a timeout.
* Email or L402 creation after an ambiguous response; those endpoints do not support idempotency keys.
* Payment of a second invoice before resolving the first order.
* Cancellation after a conflict without fetching current state.
* A request rejected for validation or authentication without correcting it.

## Rate limits

* Global: 300 requests per minute per client.
* Bearer-token creation: 60 requests per minute per client.
* Poll no faster than every 5–10 seconds per active order.

## Credential handling

* Redact bearer tokens, order references, macaroons, preimages, refund invoices, and BOLT11 invoices from logs.
* Send credentials in `Authorization` headers, never query parameters.
* Do not persist secrets in browser analytics, crash reports, or support screenshots.
* Use TLS and the exact `https://api.sms4sats.com` origin.
