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

# Preview and quote a mailpiece

> Render an uncharged test proof and quote a letter or a postcard

## Overview

Quotes one letter or postcard and renders a proof of it. Nothing is printed or charged. Both addresses are validated first. A letter's price counts its PDF pages. Free.

Rendering can take a moment: the quote comes back with `status: "rendering"` and no price. Poll [Get a quote](https://docs.oneshotagent.com/api-reference/physical-mail/quote.md) until `status` is `ready`, then show `preview.url` and `total_usdc` to the person who approves. A quote expires 30 minutes after it is created.

## Authentication

`X-Agent-ID` plus a signed `x-agent-proof` with `scope: "write"`, or an access token. See [proof authentication](https://docs.oneshotagent.com/sdk/overview.md#read-authentication). 60 requests a minute per agent.

## Request Body

**to** `object` *required*

Recipient address: `name`, `address_line1`, `address_line2` (optional), `address_city`, `address_state` (two letters), `address_zip` (5 or 9 digits), `address_country` (optional, `US`). See [Validate an address](https://docs.oneshotagent.com/api-reference/physical-mail/validate-address.md).

**from** `object` *required*

Return address, same shape as `to`

**artwork** `object` *required*

Letter: `{ "kind": "letter", "file": "<asset_id of a PDF>", "color": false, "double_sided": false }`. `color` and `double_sided` default to `false`. Postcard: `{ "kind": "postcard", "front": "<asset_id>", "back": "<asset_id>" }`. Asset IDs come from [Upload artwork](https://docs.oneshotagent.com/api-reference/physical-mail/assets.md).

## Response

The quote. Its fields are listed on [Get a quote](https://docs.oneshotagent.com/api-reference/physical-mail/quote.md#response).

```bash cURL theme={null}
curl -X POST https://win.oneshotagent.com/v1/tools/physical-mail/preview \
  -H "Content-Type: application/json" \
  -H "X-Agent-ID: 0xYourWalletAddress" \
  -H "x-agent-proof: <base64 signed proof, scope=write>" \
  -d '{
    "to": { "name": "Jane Doe", "address_line1": "185 Berry St", "address_city": "San Francisco", "address_state": "CA", "address_zip": "94107" },
    "from": { "name": "Acme Inc", "address_line1": "1 Main St", "address_city": "Austin", "address_state": "TX", "address_zip": "78701" },
    "artwork": { "kind": "letter", "file": "00000000-0000-4000-8000-000000000000", "color": false, "double_sided": false }
  }'
```

```typescript SDK theme={null}
import { OneShot } from "@oneshot-agent/sdk";

const agent = new OneShot({ privateKey: process.env.AGENT_PRIVATE_KEY });

let quote = await agent.physicalMail.preview({
  to: { name: "Jane Doe", address_line1: "185 Berry St", address_city: "San Francisco", address_state: "CA", address_zip: "94107" },
  from: { name: "Acme Inc", address_line1: "1 Main St", address_city: "Austin", address_state: "TX", address_zip: "78701" },
  artwork: { kind: "letter", file: asset.asset_id, color: false, double_sided: false },
});

while (quote.status !== "ready") {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  quote = await agent.physicalMail.getQuote(quote.quote_id);
}
```

```python Python theme={null}
quote = client.physical_mail.preview({
    "to": {"name": "Jane Doe", "address_line1": "185 Berry St", "address_city": "San Francisco", "address_state": "CA", "address_zip": "94107"},
    "from": {"name": "Acme Inc", "address_line1": "1 Main St", "address_city": "Austin", "address_state": "TX", "address_zip": "78701"},
    "artwork": {"kind": "letter", "file": asset["asset_id"], "color": False, "double_sided": False},
})
```

```json Rendering theme={null}
{
  "quote_id": "00000000-0000-4000-8000-000000000000",
  "input": {
    "to": { "name": "Jane Doe", "address_line1": "185 BERRY ST", "address_city": "SAN FRANCISCO", "address_state": "CA", "address_zip": "94107", "address_country": "US" },
    "from": { "name": "Acme Inc", "address_line1": "1 MAIN ST", "address_city": "AUSTIN", "address_state": "TX", "address_zip": "78701", "address_country": "US" },
    "artwork": { "kind": "letter", "file": "00000000-0000-4000-8000-000000000000", "color": false, "double_sided": false }
  },
  "input_hash": "<64 hex characters>",
  "status": "rendering",
  "preview": { "url": null, "thumbnails": [] },
  "total_usdc": null,
  "service_fee_usdc": null,
  "expires_at": "2026-10-29T12:30:00.000Z",
  "approval_id": null,
  "delivery_proves_readership": false
}
```

```json Address Not Deliverable (422) theme={null}
{
  "error": "address_not_deliverable"
}
```

## Errors

| Code | When |
| - | - |
| `400 invalid_input` | See `details` |
| `400 letter_requires_pdf` | A letter's `file` is not a PDF |
| `404 artwork_not_found` | No such asset for this agent |
| `422 address_not_deliverable` | `to` or `from` is undeliverable |
| `422 invalid_letter_pdf`, `422 unsupported_letter_length` | Unreadable PDF, or not 1 to 60 pages |
| `503 mail_rate_unavailable` | Retry |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.