---
title: "Create one order for an approved draft and exact total. Reuse idempotency_key on retries."
method: POST
path: "/v1/letters"
---

# Create one order for an approved draft and exact total. Reuse idempotency_key on retries.

`POST /v1/letters`

## Request

- Base URL: `https://paperagent.dev`
- URL: `https://paperagent.dev/v1/letters`
- Auth: one of:
  - OAuth 2 (authorization code, authorization URL `https://paperagent.dev/oauth/authorize`, token URL `https://paperagent.dev/oauth/token`, scopes: `letters:write`)
  - API key in header `X-Api-Key`
  - HTTP bearer

## Request body

- object
  - `draft_id` string, required
  - `confirm_total_cents` integer, required
  - `idempotency_key` string, required

## Response `202`

Success

- object
  - `letter_id` string, required
  - `order_id` string, required
  - `status` 'pending_payment' | 'pending_moderation' | 'held_for_review' | 'queued' | 'printed' | 'postage_applied' | 'accepted_by_usps' | 'in_transit' | 'arrived_at_destination_facility' | 'expected_delivery' | 'delivered' | 'blocked' | 'cancelled' | 'payment_abandoned' | 'returned', required: Where the letter is. expected_delivery is the last state a standard or proof-of-mailing letter reaches; only certified tiers ever reach delivered.
  - `checkout_url` string, nullable, required
  - `payment_url` string
  - `payment_options` object
    - `provider` 'stripe', required
    - `methods` string[], required
    - `network_id` string, required
    - `currency` 'usd', required
    - `amount_cents` integer, required
    - `livemode` boolean, required
  - `payment_status` 'requires_action' | 'processing' | 'unknown'
  - `quote` object, required: A priced letter. State total.display to the user before sending, and pass total.amount_cents as confirm_total_cents.
    - `quote_id` string, required: Identifier for this quote, for support and receipts.
    - `expires_at` string, required: ISO 8601 instant after which this total is re-computed from the live price card. Call preview_draft for a fresh quote before sending if it has passed.
    - `version` string, required: The published price card this total came from.
    - `subtotal` object, required: What the letter costs, before sales tax.
      - `amount_cents` integer, required: The amount in whole US cents.
      - `currency` 'USD', required
      - `display` string, required: The amount formatted for a person, with a currency symbol.
    - `tax` object, required
      - `collected` object, required: New York sales tax on this letter. We mail from New York, so a few cents apply wherever the letter goes, and more when it is going to New York.
        - `amount_cents` integer, required: The amount in whole US cents.
        - `currency` 'USD', required
        - `display` string, required: The amount formatted for a person, with a currency symbol.
      - `destination_state` string, required
    - `total` object, required: Subtotal plus sales tax. This is the number send_letter requires in confirm_total_cents.
      - `amount_cents` integer, required: The amount in whole US cents.
      - `currency` 'USD', required
      - `display` string, required: The amount formatted for a person, with a currency symbol.
  - `mail_date_estimate` string, required
  - `message` string, required

## Other responses

- `default`: A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.

---

[API](https://skmtc.dev/paperagent/apis/paperagent-rest-api.md) · [All operations](https://skmtc.dev/paperagent/apis/paperagent-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/paperagent/apis/paperagent-rest-api/revisions/388148938051?raw)
