> ## Documentation Index
> Fetch the complete documentation index at: https://docs.packageretriever.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Code Reference

> Every error code the Package Retriever API returns, with HTTP status, description, and fix.

# Error Code Reference

Every error follows this format:

```json theme={null}
{
  "error": {
    "code": "RESOURCE.CATEGORY.SPECIFIC",
    "message": "Human-readable description.",
    "suggestion": "What to do next.",
    "docs_url": "https://docs.packageretriever.com/reference/errors#CODE",
    "request_id": "req_xxxxxxxxx"
  }
}
```

Catch error categories programmatically:

```typescript theme={null}
if (error.code.startsWith('LABEL.')) { /* handle label errors */ }
if (error.code.startsWith('WALLET.')) { /* handle wallet errors */ }
```

***

## Authentication Errors

| Code                             | HTTP | Description                     | Fix                                                       |
| -------------------------------- | ---- | ------------------------------- | --------------------------------------------------------- |
| `AUTH.KEY.MISSING`               | 401  | No Authorization header         | Add `Authorization: Bearer pr_live_YOUR_KEY`              |
| `AUTH.KEY.INVALID`               | 401  | Key not found or malformed      | Check key format: `pr_live_` or `pr_test_` + 32 hex chars |
| `AUTH.KEY.REVOKED`               | 401  | Key has been revoked            | Create a new key in dashboard                             |
| `AUTH.KEY.EXPIRED`               | 401  | Key past expiration date        | Create a new key or update expiration                     |
| `AUTH.KEY.INSUFFICIENT_SCOPE`    | 403  | Key missing required scope      | Add the required scope to your key or create a new one    |
| `AUTH.KEY.SANDBOX_IN_PRODUCTION` | 403  | Test key used for live resource | Use a `pr_live_` key                                      |
| `AUTH.RATE_LIMIT.EXCEEDED`       | 429  | Too many requests               | Wait for `Retry-After` seconds                            |

## Validation Errors

| Code                        | HTTP | Description            | Fix                                      |
| --------------------------- | ---- | ---------------------- | ---------------------------------------- |
| `VALIDATION.FIELD.REQUIRED` | 422  | Required field missing | Include the field named in `error.field` |
| `VALIDATION.FIELD.INVALID`  | 422  | Field value invalid    | Check constraints in API reference       |

## Rate Errors

| Code                       | HTTP | Description                | Fix                                                                     |
| -------------------------- | ---- | -------------------------- | ----------------------------------------------------------------------- |
| `RATE.EXPIRED`             | 422  | Rate older than 15 minutes | Re-fetch rates via `POST /v1/rates` and use new rate\_id                |
| `RATE.NOT_FOUND`           | 404  | Rate ID doesn't exist      | Fetch rates first, then use a rate\_id from the response                |
| `RATE.CARRIER.UNAVAILABLE` | 503  | A carrier API is down      | Rates from other carriers are still returned; retry for missing carrier |

## Label Errors

| Code                           | HTTP | Description                           | Fix                                                       |
| ------------------------------ | ---- | ------------------------------------- | --------------------------------------------------------- |
| `LABEL.ADDRESS.UNDELIVERABLE`  | 422  | Carrier can't deliver to this address | Validate address first with `POST /v1/addresses/validate` |
| `LABEL.WEIGHT.EXCEEDED`        | 422  | Package over carrier max weight       | Reduce weight or use freight                              |
| `LABEL.SERVICE.UNAVAILABLE`    | 422  | Service not available for this route  | Re-fetch rates to see available services                  |
| `LABEL.VOID.INELIGIBLE`        | 422  | Carrier has scanned the package       | Cannot void after first carrier scan                      |
| `LABEL.VOID.ALREADY_REQUESTED` | 422  | Void already in progress              | Check status via `GET /v1/labels/:id`                     |
| `LABEL.NOT_FOUND`              | 404  | Label ID doesn't exist                | Check the label ID                                        |
| `LABEL.CREATION.FAILED`        | 500  | Unexpected error during creation      | Retry; contact support with request\_id if persistent     |

## Wallet Errors

| Code                            | HTTP | Description          | Fix                                     |
| ------------------------------- | ---- | -------------------- | --------------------------------------- |
| `WALLET.INSUFFICIENT_BALANCE`   | 402  | Not enough funds     | Top up wallet, then retry               |
| `WALLET.PAYMENT.FAILED`         | 402  | Card charge declined | Update payment method in dashboard      |
| `WALLET.PAYMENT_METHOD.MISSING` | 402  | No card on file      | Add a payment method in wallet settings |

## Carrier Account Errors

| Code                                  | HTTP | Description                  | Fix                                                |
| ------------------------------------- | ---- | ---------------------------- | -------------------------------------------------- |
| `CARRIER.ACCOUNT.INVALID_CREDENTIALS` | 422  | Carrier rejected credentials | Verify credentials in dashboard                    |
| `CARRIER.ACCOUNT.NOT_FOUND`           | 404  | Account ID doesn't exist     | List accounts via `GET /v1/carrier-accounts`       |
| `CARRIER.ERROR.UNKNOWN`               | 502  | Unexpected carrier error     | Retry; check `raw_carrier_error` field for details |

## Batch Errors

| Code                       | HTTP | Description                | Fix                                     |
| -------------------------- | ---- | -------------------------- | --------------------------------------- |
| `BATCH.SIZE.EXCEEDED`      | 422  | More than 5,000 items      | Split into multiple batches             |
| `BATCH.ITEMS.REQUIRED`     | 422  | Empty items array          | Provide at least 1 item                 |
| `BATCH.NOT_FOUND`          | 404  | Batch ID doesn't exist     | Check the batch ID                      |
| `BATCH.ALREADY_PROCESSING` | 422  | Buy called on active batch | Poll `GET /v1/batches/:id` for progress |

## Address Errors

| Code                               | HTTP | Description                         | Fix                                        |
| ---------------------------------- | ---- | ----------------------------------- | ------------------------------------------ |
| `ADDRESS.VALIDATION.FAILED`        | 422  | Address is undeliverable            | Check for typos; try a different address   |
| `ADDRESS.VALIDATION.AMBIGUOUS`     | 422  | Multiple possible matches           | Use one of the suggestions in the response |
| `ADDRESS.VALIDATION.SERVICE_ERROR` | 503  | Validation service temporarily down | Retry in a few seconds                     |

## Tracker Errors

| Code                | HTTP | Description              | Fix                                    |
| ------------------- | ---- | ------------------------ | -------------------------------------- |
| `TRACKER.NOT_FOUND` | 404  | Tracker ID doesn't exist | Register via `POST /v1/trackers` first |
