api. or mcp.
subdomains yet. Examples below use https://<your-assigned-host>
as a placeholder.
https://<your-assigned-host>/v1"idempotency_key": "<uuid>" in the POST /jobs body — one fresh UUID per user-confirmed action. Retrying with the same key returns the original job (200) instead of creating a duplicate (201). The server also attaches its own per-job Idempotency-Key to the print-fulfilment call, and the payment webhook is safe to receive twice.| Method & path | What it does |
|---|---|
| POST /v1/quotes | Exact per-letter quote. Retail is always 2× the underlying print + postage cost. |
| POST /v1/jobs | Create a letter job from a quote. Returns the job and its one-tap Stripe Checkout URL. |
| POST /v1/webhooks/stripe | Stripe webhook. On checkout.session.completed the job is fulfilled (the letter is created with the print partner). |
| GET /v1/jobs/{job_id} | Job status, amount, and live mail status. |
| GET /v1/letters/{letter_id} | Raw print-partner letter record. |
POST /v1/quotes
Content-Type: application/json
{ "country": "CA", "color": false, "pages": 1 }
Response 201:
{
"quote_id": "q_fa6f8c0034374ea4",
"currency": "CAD",
"country": "CA",
"color": false,
"pages": 1,
"registered": false,
"amount_cents": 615
}
country is US or CA; pages is an
integer ≥ 1. Set registered to true for registered mail
(US: certified with tracking; CA: registered with signature). Quote the exact amount_cents
to the user and get explicit
approval before creating the job. Published retail prices: US B&W $2.12, US colour
$2.44, +$0.20/+$0.40 per extra page (USD), US registered B&W $10.40; Canada B&W C$6.15, Canada colour C$6.44,
+C$0.58/+C$0.87 per extra page (CAD), Canada registered B&W C$51.12.
POST /v1/jobs
Content-Type: application/json
{
"quote_id": "q_fa6f8c0034374ea4",
"idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
"letter": {
"to": {
"firstName": "Jane", "lastName": "Doe",
"addressLine1": "123 Main St", "city": "Toronto",
"provinceOrState": "ON", "postalOrZip": "M4B 1B3",
"countryCode": "CA"
},
"from": {
"companyName": "Sam Smith",
"addressLine1": "456 Oak Ave", "city": "Markham",
"provinceOrState": "ON", "postalOrZip": "L6B 0P6",
"countryCode": "CA"
},
"html": "<html><body><p>Dear landlord, please fix the tap. — Sam</p></body></html>"
}
}
Response 201 (or 200 with the identical body if the
idempotency_key was already used — no duplicate job, no second charge):
{
"job_id": "job_8f42k1ab9c0d2e3f",
"status": "awaiting_payment",
"amount_cents": 615,
"amount": "C$6.15",
"currency": "CAD",
"checkout_url": "https://checkout.stripe.com/c/...",
"payment_mode": "real"
}
to/from require addressLine1, city,
and countryCode (US/CA). Send html
or pdf_url. The quote's country must match the destination country.
Hand checkout_url to the user — one tap, one card payment, one letter.
Point Stripe at POST /v1/webhooks/stripe. On
checkout.session.completed the server marks the job paid and creates the
letter with the print partner — fulfilment starts only after payment succeeds.
Duplicate deliveries return the already-created letter instead of mailing twice.
GET /v1/jobs/job_8f42k1ab9c0d2e3f
{
"job_id": "job_8f42k1ab9c0d2e3f",
"status": "fulfilled",
"amount_cents": 615,
"amount": "C$6.15",
"currency": "CAD",
"letter_id": "letter_v3cwk7Nwm13XRGHwkSzSsE",
"mail_status": "ready — in the print queue",
"error": null
}
Job status: awaiting_payment → paid →
fulfilled (or failed). mail_status maps the
print partner's state: ready (in the print queue), printing, processed for delivery,
completed, cancelled. completed means most likely delivered — never
report it as confirmed delivery.
All errors look like this:
{ "error": "quote is for US but destination is CA; request a new quote" }
| HTTP | Meaning |
|---|---|
| 400 | Bad request — fix the fields named in the message and retry. |
| 401 | Webhook signature check failed (real-Stripe mode only). |
| 404 | Unknown job or letter id. |
| 409 | Job is in a state that can't be fulfilled (e.g. already failed). |
| 502 | The print partner call failed; the job is marked failed with details. |
Prefer tools over HTTP? mcp-tools.json defines
quote_letter, create_letter_job, and
get_job_status with the exact shapes above. The hosted MCP transport is
assigned during private testing.
Home · Contact: hello@getletteragent.com · No cookies. No tracking.