Send a letter
Create a physical letter from a PDF and a postal address, then list, fetch, cancel, and price letters over the API.
Create a letter from a PDF and a postal address, then follow it by id. This page covers the core letter operations; letter templates and batches have their own pages.
| Operation | Method & path | Scope |
|---|---|---|
| Create a letter | POST /v1/letters | letters:send |
| List letters | GET /v1/letters | letters:read |
| Get a letter | GET /v1/letters/{id} | letters:read |
| Cancel a letter | POST /v1/letters/{id}/cancel | letters:send |
| List letter events | GET /v1/letters/{id}/events | letters:read |
| Price a letter | POST /v1/letters/price | letters:read |
Create a letter
Pass the PDF as pdfBase64, a fileName, and a recipient to address.
Everything else has defaults.
The response is the letter object at status: "queued" — accepted and being
prepared, nothing printed yet. pageCount and price are null until the
letter is priced.
Always pass an Idempotency-Key header (or idempotencyKey in the SDKs) when
creating letters. A retried create with the same key returns the original
letter instead of printing a second one — physical mail cannot be unsent. See
Retries & idempotency. In the CLI, dairo letter send
creates a draft unless you pass --confirm, so an accidental rerun never
posts anything.
Document sources
A letter's document comes from exactly one of three sources:
| Source | What it is |
|---|---|
pdfBase64 | The PDF inline, base64-encoded. |
file | A PDF already in Dairo — either an email attachment (attachmentId, with an optional informational messageId) or a storage object (objectId). Exactly one of the two; the storage object must have passed its malware scan. |
templateId | A stored letter template, rendered with templateData and the recipient composited into the address window. |
The document must be a real PDF no larger than 25 MB. A non-PDF is rejected
with 422; an oversize file with 413. Providing more than one source — or
none — is a 400.
Bringing your own PDF? It must follow the
layout contract — A4 portrait, the
recipient address inside the envelope window, franking zones clear, fonts
embedded. POST /v1/letters/verify checks all of it and returns a structured
pass/warn/fail report before anything is printed; GET /v1/letters/requirements returns the machine-readable spec plus compliant
starter templates.
Request fields
| Field | Required | Description |
|---|---|---|
pdfBase64 / file / templateId | one of | The document source — exactly one of the three. |
fileName | yes | A name for the document, kept for your records. |
to | yes | Recipient postal address. country (ISO 3166-1 alpha-2) is required, plus a street or a poBox. |
from | no | Optional sender block, same shape as to. |
print | no | mode, sides, addressPlacement. Defaults: grayscale, simplex, left. |
delivery | no | Delivery class; defaults to economy. |
autoSend | no | true (default) queues the letter for posting; false stores it as a draft. |
templateData | no | Values that fill the template's {{placeholders}}; used only with templateId. |
payment / paymentSlip | no | Add a payment slip — see Print & delivery options. |
notifications | no | Owner milestone emails for this letter; defaults to true. |
metadata | no | Opaque JSON object (up to 8 KB), stored and echoed back. |
The recipient's country must be a destination Dairo can deliver to. An
unsupported or malformed country is rejected with 422 naming to.country.
List letters
List your letters, most recent first. Page with limit (1–100, default 20)
and cursor using keyset pagination, and filter by
status, country, or batchId.
List items are compact: the to block carries only the recipient's city and
country, never the full address.
Get one letter
Fetch a letter by id to read its current status, price, and its full
address, with the delivery events timeline inlined newest first (up to 100
events). The print partner reports no tracking numbers, so follow a letter by its
status and events. Fetching an
in-flight letter also refreshes its tracking state, so a poll returns the latest
known status.
price is what this letter was priced and charged at (amounts elided here:
postage changes, so quote a letter for a current price). A
letter id that is unknown or not yours returns 404 — the two cases are
indistinguishable by design.
Cancel a letter
Cancel a letter that has not been dispatched. Cancellation is allowed while
the letter is draft, queued, processing, printable, or submitted —
once it is in_transit it is in the postal network and cannot be recalled.
You get back the letter with status: "canceled" and canceledAt set.
Canceling a letter that is already past dispatch returns 409 Conflict with
code: "letter_not_cancelable".
List a letter's events
Fetch the delivery timeline on its own. Events come back newest first, up to the 100 most recent.
The event field reference is on Status & tracking.
Price a letter
A letter's cost depends on its page count, print options, delivery class, and
destination. POST /v1/letters/price returns the exact cost without creating
a letter — pass a pageCount, or the pdfBase64 itself and Dairo counts the
pages.
The full request reference, the quote-then-send pattern, and how letters bill are on Pricing.
Next steps
- Send a batch — one template, up to 1,000 recipients, in one call.
- API reference — full request and response schemas for every letters endpoint.
Physical mail (Fairo)
Turn a PDF into a real, printed letter — one API call, then Dairo prints, posts, and tracks it to the mailbox.
Layout & verification
The exact PDF layout a printed letter needs — address window, keep-out zones, fonts — plus the verify endpoint that checks a PDF before you send it.