Docs
Letters

Create a letter

Sends a document to be printed and posted.

POST
/letters

Authorization

apiKey
headerAuthorizationBearer <token>

API key in the Authorization: Bearer cf_live_... header. Create and revoke keys in the dashboard, under Desenvolvedores > Chaves de API (Developers > API keys).

Header Parameters

Idempotency-Key?string

A unique value per operation, such as the invoice id in your system or a UUID. If you repeat the request with the same key within 24 hours, the API returns the first response instead of creating another object. Recommended on every POST. Up to 255 characters.

Lengthlength <= 255

Request Body

Two formats with the same fields: application/json, with the PDF in document (URL, two-step upload or base64), or multipart/form-data, with the PDF file in the file field (up to 4 MB). Switch the format with the selector on the box below.

  1. body
to*

Recipient. CartaFlow prints these details in the address area, which shows through the envelope window.

from?

Sender, printed on one line above the recipient. Correios returns the letter to this address when it cannot be delivered, and sends the return receipt (return_receipt) here. If you leave it out, we use the account’s default sender, set in the dashboard under Configurações > Empresa (Settings > Company).

document*||

The content to print, in JSON. Pick the way with the type field: url (up to 10 MB), upload (a file sent beforehand with POST /v1/uploads, up to 10 MB) or base64 (up to 3 MB). To upload the PDF file together with the request, use multipart/form-data instead of JSON (file field, up to 4 MB). The PDF must be A4 portrait and fit in 6 sheets. See the Document and address area guide.

color?boolean

true prints in color. false prints in black and white: a color PDF comes out in grayscale. Color printing costs extra per printed page (each printed side counts as a page).

Defaultfalse
double_sided?boolean

true prints on both sides: each sheet carries two pages of the document, so the letter uses fewer sheets and costs less. false prints on the front of each sheet only.

Defaultfalse
address_placement?string

Where CartaFlow prints the recipient’s address.

Possible values

  • first_page: In the address area of your document’s first page (90 x 45 mm, 20 mm from the left and 45 mm from the top). That area must be blank in your PDF. Default.
  • extra_page: On a side of its own, the first one, which shows through the envelope window. Use it when your layout fills the address area. It takes a side that would otherwise be blank, when there is one: the back of the first page when printing on one side, or the spare side of a double-sided document with an odd number of pages. A double-sided document with an even number of pages gets one more sheet at the front. The address is never charged.
Default"first_page"
Value in"first_page""extra_page"
postal_services?array<>

Optional Correios services, each with its own surcharge (a line in price). Without this field, or with [], the letter goes as a simple letter ("carta simples"), with no tracking after posting. return_receipt and restricted_delivery only work together with registered; without it, the API answers 422 with requires_registered. In multipart/form-data, repeat the postal_services[] field once per service.

Possible values

  • registered: Registered letter ("carta registrada"): the letter is posted with registration at Correios and gets a Correios tracking code, shown in tracking_code once it is posted.
  • return_receipt: Return receipt ("aviso de recebimento", AR): Correios returns a card signed by whoever received the letter to the sender printed on the envelope. Requires registered.
  • restricted_delivery: Restricted delivery ("mão própria", MP): Correios delivers only to the person named on the envelope. Requires registered.
Default[]
send_date?string

Schedules the letter for a date, formatted YYYY-MM-DD, from tomorrow up to 180 days ahead (Brasília time). The letter is validated now but only charged on that date, at 06:00: at that moment the balance must cover the price, otherwise the letter is canceled with cancellation_reason: insufficient_balance. Until then it stays scheduled and can be canceled at no cost. To send right away, leave this field out.

Formatdate
reference?string

Your identifier for this letter, such as the invoice number or the customer id in your system. Shown in the dashboard and usable as a filter when listing. It does not have to be unique. Up to 100 characters.

Lengthlength <= 100
metadata?

Key-value pairs to store your own data with the object, such as your customer or contract id. Returned in every response and webhook and never printed. Up to 20 keys; keys up to 40 characters and string values up to 500 characters. Do not store sensitive data such as passwords or card numbers.

Propertiesproperties <= 20

Response Body

The letter was created. Status received (already charged) or scheduled (scheduled, charged on its send date).

application/json
  1. response

A physical letter: a document that CartaFlow prints, envelopes and posts to an address in Brazil.

id*string

Unique identifier of the letter. Always starts with ltr_.

Match^ltr_[A-Za-z0-9]+$
object*string

Object type. Always letter.

status*string

Where the letter is. It only moves forward, never back: scheduled (only when scheduled), received, in_production, printed, posted. From scheduled or received it can move to canceled; from received, in_production or printed, to failed. A reprint in production does not change the status.

Possible values

  • scheduled: The letter was validated and is waiting for its send_date. It has not been charged yet. On that date, at 06:00 Brasília time, CartaFlow debits the balance and the letter moves to received. If the balance does not cover the price, it moves to canceled. It can be canceled at no cost.
  • received: CartaFlow validated the document and the address, charged the letter to your balance and put it in the production queue. It can still be canceled, and the amount goes back to the balance.
  • in_production: The letter is part of a print batch. From this point on it can no longer be canceled.
  • printed: The letter was printed, folded and put in its envelope. Posting is the next step.
  • posted: The letter was handed to Correios, the Brazilian postal service. From here on delivery follows the postal service, and CartaFlow receives no further updates about it. A registered letter carries its Correios tracking code in tracking_code.
  • canceled: The letter was canceled before production and nothing was printed. cancellation_reason says why: you canceled it, or the balance did not cover a scheduled letter on its send date. If it had been charged, the amount went back to the balance.
  • failed: Something went wrong in production and the letter will not be posted. failure_reason says why. The amount went back to the balance automatically.
Value in"scheduled""received""in_production""printed""posted""canceled""failed"
to*

Recipient.

from*

Sender printed above the recipient: the one you sent or the account’s default sender.

document*||

Where the letter content came from. The final PDF is at preview_url.

color*boolean

true when printed in color.

double_sided*boolean

true when printed on both sides.

address_placement*string

Where the address is printed.

Possible values

  • first_page: In the address area of the document’s first page.
  • extra_page: On a side of its own, the first one, at no charge.
Value in"first_page""extra_page"
postal_services*array<>

The optional Correios services chosen at creation. Always a list: [] for a simple letter ("carta simples").

Possible values

  • registered: Registered letter ("carta registrada"): the letter is posted with registration at Correios and gets a Correios tracking code, shown in tracking_code once it is posted.
  • return_receipt: Return receipt ("aviso de recebimento", AR): Correios returns a card signed by whoever received the letter to the sender printed on the envelope. Requires registered.
  • restricted_delivery: Restricted delivery ("mão própria", MP): Correios delivers only to the person named on the envelope. Requires registered.
pages*integer

Number of pages in your document, not counting the address side with extra_page.

Range1 <= value
sheets*integer

Sheets of paper in the envelope. On one side, it is pages. Double-sided, it is half of pages rounded up with first_page, and half of pages rounded down, plus 1, with extra_page. At most 6, counting the sheet the address adds, which is not charged.

Range1 <= value <= 6
price*

The price of the letter. It is charged to the balance at creation or, for a scheduled letter, on its send date (on the account’s plan that day). It goes back to the balance if the letter is canceled after being charged or fails in production.

send_date*|

The scheduled send date, YYYY-MM-DD. null when the letter was sent right away.

Formatdate
cancellation_reason*|

Why the letter was canceled. null when it is not canceled.

Possible values

  • requested: You canceled it, through the API or the dashboard.
  • insufficient_balance: It was a scheduled letter and, on the send date, the balance did not cover the price. Nothing was charged.
Value in"requested""insufficient_balance"null
failure_reason*|

Why the letter failed in production. null when it is not failed. When a letter fails, the amount goes back to the balance automatically.

Possible values

  • unprintable_document: The file passed validation but could not be printed as it is.
  • damaged_in_production: The letter was damaged in printing, folding or enveloping and could not be produced again.
  • refused_by_carrier: Correios refused the letter at posting.
  • other: Another reason. Contact CartaFlow support from the dashboard for the details.
Value in"unprintable_document""damaged_in_production""refused_by_carrier""other"null
tracking_code*|

The Correios tracking code of a registered letter (postal_services with registered), such as RA123456785BR. Filled in when the letter is posted. null for a simple letter, which has no tracking, and before posting.

preview_url*|

Link to the final PDF, exactly as it will be printed, address included. The link works for 60 minutes: retrieve the letter again for a fresh link. The file stays available for at least 90 days after creation (or after the send date, for a scheduled letter); null only after that, if the file is no longer available. For a black-and-white letter the PDF keeps the original colors: the conversion to grayscale happens at printing.

Formaturi
reference*|

Your identifier for this letter, such as the invoice number or the customer id in your system. Shown in the dashboard and usable as a filter when listing. It does not have to be unique. Up to 100 characters. null when you did not send one.

Lengthlength <= 100
metadata*

Key-value pairs to store your own data with the object, such as your customer or contract id. Returned in every response and webhook and never printed. Up to 20 keys; keys up to 40 characters and string values up to 500 characters. Do not store sensitive data such as passwords or card numbers. Empty object {} when you did not send any.

Propertiesproperties <= 20
status_transitions*

When the letter reached each status. null for statuses it has not reached. A scheduled letter starts as scheduled, at created_at.

created_at*string

When the letter was created and received, in UTC.

Formatdate-time
curl -X POST "https://api.cartaflow.com.br/v1/letters" \  -H "Authorization: Bearer $CARTAFLOW_API_KEY" \  -H "Content-Type: application/json" \  -d '{  "to": {    "name": "Destinatário Exemplo",    "postal_code": "01001-000",    "number": "128",    "complement": "Ap. 52"  },  "document": {    "type": "url",    "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf"  },  "color": true,  "reference": "fatura-2026-10-0042",  "metadata": {    "customer_id": "1842"  }}'

{  "id": "ltr_8Kq2wX4mN7pR",  "object": "letter",  "status": "received",  "to": {    "name": "Destinatário Exemplo",    "street": "Praça da Sé",    "number": "128",    "complement": "Ap. 52",    "neighborhood": "Sé",    "city": "São Paulo",    "state": "SP",    "postal_code": "01001-000"  },  "from": {    "name": "Exemplo Serviços Ltda.",    "street": "Avenida Exemplo",    "number": "1000",    "complement": "Sala 301",    "neighborhood": "Bela Vista",    "city": "São Paulo",    "state": "SP",    "postal_code": "01310-100"  },  "document": {    "type": "url",    "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf",    "variables": null  },  "color": true,  "double_sided": false,  "address_placement": "first_page",  "postal_services": [],  "pages": 2,  "sheets": 2,  "price": {    "currency": "BRL",    "total": 1135,    "items": [      {        "type": "base",        "quantity": 1,        "unit_amount": 990,        "amount": 990      },      {        "type": "additional_sheets",        "quantity": 1,        "unit_amount": 75,        "amount": 75      },      {        "type": "color",        "quantity": 2,        "unit_amount": 35,        "amount": 70      }    ]  },  "send_date": null,  "cancellation_reason": null,  "failure_reason": null,  "tracking_code": null,  "preview_url": "https://files.cartaflow.com.br/previews/ltr_8Kq2wX4mN7pR.pdf?expires=1760369400&signature=9c1f2a7d",  "reference": "fatura-2026-10-0042",  "metadata": {    "customer_id": "1842"  },  "status_transitions": {    "received_at": "2026-10-13T14:20:00Z",    "in_production_at": null,    "printed_at": null,    "posted_at": null,    "canceled_at": null,    "failed_at": null  },  "created_at": "2026-10-13T14:20:00Z"}