# Errors

URL: https://docs.lastscanned.com/errors

Every error has the same shape:

```json
{ "error": { "code": "not_found", "message": "UPS returned no track details for that number" } }
```

Branch on `code`; `message` is for people and can change.

| HTTP | `code` | When | Retry? |
|---|---|---|---|
| 400 | `bad_request` | No numbers, more than 100, or more than 35 for one carrier | No |
| 400 | `unknown_carrier` | No carrier's format matches the number (or its check digit is wrong), or an unsupported `carrier` | Fix the number or pass `carrier` |
| 401 | `unauthorized` | Missing, wrong or revoked key, or a disabled account | No |
| 402 | `payment_required` | No key, and no free lookup left (or a request for several numbers) | Pay with MPP; see [Pay per request](/authentication#pay-per-request) |
| 402 | `credits_used` | A credit key doesn't have enough credits left for the request | Pay again without the key |
| 404 | `not_found` | The carrier has no record of the number, or no such key or route | Later; new labels can take a while to appear |
| 429 | `free_lookup_used` | No key, and this IP's free lookup for today is used (when pay per request is off) | Sign up for a key, or after 00:00 UTC |
| 429 | `rate_limited` | Daily limit reached, or the carrier is throttling (Spee-Dee) | After 00:00 UTC, or in a minute for Spee-Dee |
| 500 | `internal_error` | Unexpected failure | Yes |
| 500 | `not_configured` | The service is misconfigured | Yes |
| 502 | `carrier_error` | The carrier failed or blocked the lookup | Yes |

On `GET /v1/track?numbers=`, per-number errors (`not_found`, `unknown_carrier`, `carrier_error`, `rate_limited`) are returned inside `results` with a `200`; only a malformed request, a bad key or the daily limit fails the whole call.

Over MCP, a failed tool call returns this same object as a result with `isError: true`.
