> ## 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.

# Sandbox & Testing

> Test your integration without real billing or real labels using sandbox API keys.

# Sandbox & Testing

Use a `pr_test_` key to test your integration. No billing occurs. No real labels are created. No carrier APIs are called.

## How sandbox works

* Same base URL: `https://api.packageretriever.com/v1/`
* Same endpoints, same response shapes
* Determined entirely by your API key prefix
* Sandbox responses include `"sandbox": true` in every response

```typescript theme={null}
// Production
const pr = new PackageRetriever('pr_live_a1b2c3...');

// Sandbox — same code, different key
const pr = new PackageRetriever('pr_test_a1b2c3...');
```

## What differs in sandbox

| Behavior           | Live                  | Sandbox                              |
| ------------------ | --------------------- | ------------------------------------ |
| Carrier API calls  | Real                  | Simulated (fixtures)                 |
| Wallet deductions  | Real charges          | Infinite balance (\$9,999.99)        |
| Label URLs         | Real PDFs             | Sample PDF                           |
| Tracking numbers   | Real carrier-issued   | Start with `9999`                    |
| Webhooks           | Delivered to your URL | Delivered to your URL (test payload) |
| Address validation | Google + FedEx APIs   | Fixture responses                    |

## Magic test values

Use these special values to trigger specific outcomes in sandbox mode:

### Addresses

| Street value            | Outcome                                                 |
| ----------------------- | ------------------------------------------------------- |
| `1 Test Success Rd`     | Validates successfully, residential                     |
| `2 Test Commercial Ave` | Validates successfully, commercial                      |
| `9 Test Failure Ln`     | Returns `ADDRESS.VALIDATION.FAILED`                     |
| `10 Test Ambiguous Ct`  | Returns `ADDRESS.VALIDATION.AMBIGUOUS` with suggestions |

### ZIP codes

| ZIP     | Outcome                                                              |
| ------- | -------------------------------------------------------------------- |
| `00000` | All carriers return empty rates (simulates all carriers unavailable) |
| `99999` | USPS excluded from rate results                                      |

### Weights

| Weight (oz) | Outcome                                                            |
| ----------- | ------------------------------------------------------------------ |
| `99999`     | Returns `LABEL.WEIGHT.EXCEEDED`                                    |
| `1`         | Returns cheapest possible rates (\$3-5 range)                      |
| `88888`     | Returns `WALLET.INSUFFICIENT_BALANCE` regardless of actual balance |

### Tracking

| Tracking number       | Outcome                                          |
| --------------------- | ------------------------------------------------ |
| `9999000000000000001` | Returns a complete delivered timeline (6 events) |
| Any `9999...` number  | Returns in-transit timeline (3 events)           |

## Dashboard sandbox indicator

When your account has active sandbox keys, a yellow banner appears at the top of the dashboard:

> **Sandbox mode active** — API calls with test keys return simulated data. No billing occurs.

This helps you visually confirm you're testing, not accidentally operating in production.

## Testing webhooks

Sandbox mode delivers real webhook payloads to your configured URL — the only difference is the `label.tracking_number` starts with `9999` and the payload includes `"sandbox": true`.

Use a tool like [webhook.site](https://webhook.site) to inspect payloads during development.

## Going live

1. Verify your sandbox integration works end-to-end
2. Fund your wallet (minimum \$5)
3. Create a `pr_live_` key with the same scopes
4. Replace the key in your environment variables
5. Your first real label is one API call away
