# Errors and rate limits

Errors use standard HTTP status codes and a JSON body with a detail message. Most of them tell you exactly what to do next.

## What does a 409 from the SMS Nitro API mean?

409 means no number is available right now for that app and country. Try another country, or set server to the other one, and buy again. It is never charged.

## Status codes

| HTTP | Meaning | What to do |
|---|---|---|
| 400 | Request not possible now: country not sold for that app, order already closed, number expired, cancel too early | Read detail and adjust. Early cancel: wait 2 minutes |
| 401 | Missing, invalid or revoked API key | Check the header and the key in the dashboard |
| 402 | Insufficient balance | Top up, then retry |
| 404 | Order not found, or app unavailable on that server | Check the id, product and server |
| 409 | No number available right now | Try another country or server |
| 422 | Invalid body or parameter. Here detail is a list of field errors | Fix the fields listed in detail |
| 429 | Rate limit reached | Wait and retry with backoff |
| 502 | Upstream supply temporarily unavailable | Retry in a few seconds |

**Error body**

```http
HTTP/1.1 402 Payment Required
Content-Type: application/json

{ "detail": "Insufficient balance" }
```

## Rate limits

- POST /v1/orders: 500 purchases per minute per account and per IP.
- POST /v1/orders/{id}/resend: 30 requests per minute.
- Polling: one GET per order every 3 to 5 seconds is enough. Faster polling does not make the SMS arrive sooner.

## Retry strategy

Retry 429 and 502 with exponential backoff. Do not retry 400, 401, 402 or 404 without changing the request. A purchase that failed with 409 or 502 was not charged, so it is safe to buy again.

**Python helper**

```python
import random, time, requests

def call(method, url, **kw):
    for attempt in range(5):
        r = requests.request(method, url, timeout=30, **kw)
        if r.status_code == 429:
            time.sleep(float(r.headers.get("Retry-After", 2 ** attempt)))
            continue
        if r.status_code in (502, 503, 504):
            time.sleep(2 ** attempt + random.random())
            continue
        return r
    r.raise_for_status()
    return r
```

## FAQ

**Am I charged when a request fails?** No. Failed purchases never create a charge, and orders without an SMS are refunded.

Source: https://smsnitro.com/developers/errors
