> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.usglobalmail.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.usglobalmail.com/_mcp/server.

# Sandbox

Some things that happen to your mailbox are done by **USGM operators in the warehouse**, on physical
mail — not by you through the API. Two in particular:

* **Mail arriving.** New mail items appear when an operator receives and logs a physical piece.
* **A scan being performed.** When you request a scan, an operator physically scans the item; only then
  does the scan reach `COMPLETED` with a downloadable file.

In production there's no API to make those happen — they're real-world actions. But while you're
**building against the sandbox**, there's no warehouse and no physical mail, so you'd have nothing to
list, scan, or ship. The sandbox module fills that gap: a small set of endpoints that let you
**simulate the operator's side** so you can exercise your whole integration without waiting on real mail.

> **Warning**
>
> These endpoints exist **only on the sandbox** (`https://api-sandbox.usglobalmail.com`, with a
> `usgmk_test_…` key). They return `404` on production — there is no operator to fake there.

## Seed mailbox

`POST /v1/sandbox/seed` — populate your sandbox mailbox with a ready-made set of sample mail items in
one call. Takes no body; returns the ids of everything it created.

```bash
curl -X POST https://api-sandbox.usglobalmail.com/v1/sandbox/seed \
  -H "Authorization: Bearer $USGM_TEST_KEY"
```

```json
{ "mail_ids": ["100001", "100002", "100003"] }
```

Use it once at the start of a test run to get a populated inbox to list, filter, organize, and scan.

## Seed mail

`POST /v1/sandbox/seed/mail` — add a **single** mail item, shaped to the case you're testing. Every
field is optional; omit the body entirely to get a sample letter.

| Field         | Notes                                                                    |
| ------------- | ------------------------------------------------------------------------ |
| `sender_name` | Who the item is from.                                                    |
| `mail_type`   | `LETTER`, `LARGELETTER`, `MAGAZINE`, `CATALOG`, `SOFTPAK`, or `PACKAGE`. |
| `weight`      | Item weight, in pounds — drives shipping quotes.                         |
| `measurement` | `{ width, height, length }` in inches — drives shipping quotes.          |

The `mail_type` matters: `LETTER` and `LARGELETTER` accept a flat **`SCAN_REQUEST`**, while the bulkier
types accept an **`UNBOXING_REQUEST`** (open-and-scan) — so seed the type that matches the scan flow
you want to test.

```bash
curl -X POST https://api-sandbox.usglobalmail.com/v1/sandbox/seed/mail \
  -H "Authorization: Bearer $USGM_TEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sender_name": "Internal Revenue Service",
    "mail_type": "PACKAGE",
    "weight": 2.5,
    "measurement": { "width": 8, "height": 4, "length": 10 }
  }'
```

```json
{ "mail_id": "100004" }
```

## Complete scan

`POST /v1/sandbox/scans/{id}/complete` — force one of your **pending** scan requests to `COMPLETED`,
standing in for the operator who would physically scan the item. Pass the scan's `id` — the `id` returned by
`POST /v1/scans` when you requested the scan — in the path.

The sandbox has no scanning AI, so the body (optional) lets you supply the `label` and `summary` the AI
would normally generate — handy for exercising the scan's `label` field and the
`GET /v1/scans/{id}/summary` endpoint.

| Field     | Notes                                                                         |
| --------- | ----------------------------------------------------------------------------- |
| `label`   | Short document label, e.g. `"Insurance"` — set on the scan.                   |
| `summary` | Up to 20 summary bullet points; retrievable via `GET /v1/scans/{id}/summary`. |

```bash
curl -X POST https://api-sandbox.usglobalmail.com/v1/sandbox/scans/SCAN_ID/complete \
  -H "Authorization: Bearer $USGM_TEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Insurance",
    "summary": ["Auto policy renewal", "Amount due: $482.00", "Due date: 2026-08-01"]
  }'
```

The response is the completed [scan](/guides/core-concepts/resource-models#scan), now with a
downloadable file.

## Putting it together

A typical end-to-end test drives your integration through the full scan lifecycle — you play both sides:

#### Seed a mail item

`POST /v1/sandbox/seed/mail` → note the returned `mail_id`. *(Simulates mail arriving.)*

#### Request a scan

`POST /v1/scans` with that `mail_id` → returns a pending scan. Note its `id` — that's the scan id you'll complete next. *(Your real integration code.)*

#### Complete the scan

`POST /v1/sandbox/scans/{id}/complete`, putting that scan `id` in the path, with a `label` and `summary`. *(Simulates the operator scanning it.)*

#### Read the results

`GET /v1/scans/{id}/file` for the download URL and `GET /v1/scans/{id}/summary` for the summary —
exactly as you would in production. *(Your real integration code.)*

> **Note**
>
> Steps 2 and 4 are your actual production code paths — only steps 1 and 3 use sandbox-only endpoints.
> When you move to production, drop the two simulation calls; real mail and real scans take their place.