Docs
Address verifications

Create a verification

Mails a letter with your brand and a 6-digit code to the address.

POST
/verifications

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

application/json
  1. body

The letter comes from the CartaFlow letter template, which you can customize in letter, or from your own PDF, in document. Send one or the other, never both. A verification always goes as a simple letter ("carta simples"): there is no postal_services here.

to*

The address to verify and the name of who lives or works there.

method*string

How the person confirms the code. It also sets what is printed on the letter.

Possible values

  • hosted_page: The person confirms on a page with your brand, hosted by CartaFlow: through the QR code, which opens the page with the code already in it, or by typing the code at the printed address. You build no screens; the result arrives by webhook and shows in the dashboard.
  • code: The letter carries only the code, with no QR code and no page address. The person types it into your website or app, and your server checks it with POST /v1/verifications/{verification_id}/check.
Value in"hosted_page""code"
letter?

Customizes the CartaFlow letter template, for this verification only. Each field you leave out comes from your company’s default letter, saved in the dashboard, and, when the company has not saved one, from the CartaFlow default. The texts sit below the envelope window. The default texts and the fixed parts, such as "Seu código" ("Your code") and the QR code instruction, are in Portuguese. Your logo, your company name, the address and the code are always printed and are not changed here. Do not use it together with document: the API answers 422 with invalid_value.

document?||

Your own PDF, instead of the CartaFlow letter template. 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). This endpoint only takes JSON: to send the file itself, use the two-step upload.

The PDF follows the rules of a letter (A4 portrait, up to 6 sheets, blank address area with address_placement: first_page, selectable text) and has reserved markers that CartaFlow fills in:

  • {{OTP_CODE}}: required. Where the code is printed, as 123 456, in the marker’s font, size and color. Without it, the API answers 422 with otp_code_missing.
  • {{VERIFICATION_URL}}: optional. The address of the confirmation page (hosted_page_url), without the code.
  • {{QR_CODE}}: optional. A 25 x 25 mm QR code that opens the page with the code already in it. Its top-left corner sits where the marker starts: leave that space blank, to the right of and below the marker.

{{VERIFICATION_URL}} and {{QR_CODE}} only work with method: hosted_page; with method: code, the API answers 422 with invalid_value. Type the markers in capitals, with the braces. Other markers, such as {{name}}, work as in a letter: send their values in variables, leaving out the reserved ones (variable_not_found).

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). Only applies with document, your own PDF. The CartaFlow letter template is always one sheet in black and white: without document, sending this field with a value other than the default gives a 422 with invalid_value.

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. Only applies with document, your own PDF. The CartaFlow letter template is always one sheet in black and white: without document, sending this field with a value other than the default gives a 422 with invalid_value.

Defaultfalse
address_placement?string

Where CartaFlow prints the recipient’s address on your PDF. Only applies with document, your own PDF. The CartaFlow letter template is always one sheet in black and white: without document, sending this field with a value other than the default gives a 422 with invalid_value.

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"
instructions?string

Text printed right below the code, on the CartaFlow letter template, telling the person where to type it. Use it with method: code, for example "Open the app, go to Profile > Address and type the code". It is also printed with method: hosted_page when letter turns off both the QR code and the page address. If you leave it out, we print "Digite este código no site ou aplicativo de" ("Type this code on the website or app of") followed by your company name. It is not printed on your own PDF: write the instruction in the document. Up to 300 characters.

Length1 <= length <= 300
return_url?string

Only for method: hosted_page. After confirming, the page shows a button that takes the person to this URL, such as the logged-in area of your site.

Formaturi
Lengthlength <= 2048
reference?string

Your identifier for this verification, 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 verification was created and charged. Status received.

application/json
  1. response

A physical address verification: CartaFlow mails a letter with a code, under your brand, and the address is verified when the person confirms the code. The code never shows in this object, nor in the dashboard.

id*string

Unique identifier of the verification. Always starts with ver_.

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

Object type. Always verification.

status*string

Where the verification is. It only moves forward: received, in_production, awaiting_code, verified. From received it can move to canceled; from in_production, to canceled (by CartaFlow) or revoked; from awaiting_code, to failed, expired or revoked; from verified, to revoked. Only verified means a confirmed address.

Possible values

  • received: CartaFlow received the request, charged the price to your balance and put the letter with the code in the production queue. If you cancel now, nothing is printed and the amount goes back to the balance.
  • in_production: The letter with the code is being printed and enveloped. Canceling now revokes the verification (revoked), with no refund.
  • awaiting_code: The letter was posted. Now we wait for the person to confirm the code. They have 60 days from posting (see expires_at). Canceling now revokes the verification, with no refund.
  • verified: The person confirmed the right code. They receive mail at the address on file. confirmation says how and when. You can still revoke the verification, which moves it to revoked.
  • failed: 5 wrong codes were entered. The verification was locked to stop guessing. Create a new verification to try again.
  • expired: 60 days went by after posting without the person confirming the code.
  • canceled: The verification was canceled before posting and the amount went back to your balance. Either you canceled it while it was received, or CartaFlow canceled it because the letter could not be produced.
  • revoked: You canceled the verification after production started: in production, awaiting the code or already verified. The amount does not go back to the balance, because production already started, and a letter that was in production is still posted. The code stops working, on the page and in the API, and the verification never shows as verified again.
Value in"received""in_production""awaiting_code""verified""failed""expired""canceled""revoked"
method*string

How the person confirms the code.

Possible values

  • hosted_page: On the page with your brand, through the QR code or by typing the code.
  • code: By typing the code into your website or app.
Value in"hosted_page""code"
source*string

Where the verification was created. It does not depend on how it is confirmed (see confirmation).

Possible values

  • api: Through the API, with POST /v1/verifications.
  • dashboard: In the dashboard, by someone on your team.
Value in"api""dashboard"
to*

The address being verified.

document*|||

How the letter was made: the CartaFlow letter template or your own PDF. A copy of it, with the code hidden (000 000), is at preview_url.

instructions*|

The text you sent to print below the code, on the CartaFlow letter template. null when you did not send one.

return_url*|

Where the page sends the person after confirming. null when not set.

Formaturi
hosted_page_url*|

The address of the confirmation page, with your brand (for now on the verifica.cartaflow.com.br domain): https://verifica.cartaflow.com.br/{your account id}/{page token}. It is the address printed on the letter and the one the QR code opens; the QR code carries the code with it, but this link does not, so whoever opens the link has to type the code. You can email this link or show it in your app. Treat it as an opaque address: store and use it as it came. null when method is code.

Formaturi
attempts_remaining*integer

How many more wrong codes can be entered. Starts at 5 and goes down with each wrong code, on the page or through the API. At 0 the verification moves to failed.

Range0 <= value <= 5
expires_at*|

Deadline for the person to confirm: 60 days after posting. null before posting.

Formatdate-time
confirmation*|

How and when the person confirmed the code: where (method), when, from which IP and from where, approximately. null until the verification is confirmed. A verification revoked after being confirmed keeps this record, but its status is revoked: the address no longer counts as verified.

preview_url*|

Link to a copy of the letter as it will be printed, address included, but without the code: in its place it shows 000 000, and in place of the QR code, a box that shows where it will be printed. The code only exists in the file CartaFlow prints: neither the API nor the dashboard can show it. The link works for 60 minutes: retrieve the verification again for a fresh link. null in events and webhooks, and when the file is not available.

Formaturi
price*

The price charged to the balance at creation. With the CartaFlow letter template, one base mailing on your plan: a single base line. With your own PDF, the price of a letter with the same options: base, additional_sheets and color. There are never Correios services. It goes back to the balance when the verification is canceled (canceled); it does not when the verification is revoked (revoked).

reference*|

Your identifier for this verification, 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 verification reached each status. null for statuses it has not reached. The received status happens at created_at. A verification revoked after being confirmed keeps verified_at.

created_at*string

When the verification was created.

Formatdate-time
curl -X POST "https://api.cartaflow.com.br/v1/verifications" \  -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"  },  "method": "hosted_page",  "return_url": "https://www.exemplo.com.br/conta",  "reference": "cliente-1842"}'

{  "id": "ver_3Hd9Kp2qZ6tW",  "object": "verification",  "status": "received",  "method": "hosted_page",  "source": "api",  "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"  },  "document": {    "type": "template",    "title": "Confirme o seu endereço",    "body": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",    "footer": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",    "include_qr_code": true,    "include_page_url": true  },  "instructions": null,  "return_url": "https://www.exemplo.com.br/conta",  "hosted_page_url": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/9Qx2Lm7Tp4Rb8Kd3Wn6Yc1",  "attempts_remaining": 5,  "expires_at": null,  "confirmation": null,  "preview_url": "https://files.cartaflow.com.br/previews/ver_3Hd9Kp2qZ6tW.pdf?expires=1760369400&signature=5d2e81b3",  "price": {    "currency": "BRL",    "total": 990,    "items": [      {        "type": "base",        "quantity": 1,        "unit_amount": 990,        "amount": 990      }    ]  },  "reference": "cliente-1842",  "metadata": {},  "status_transitions": {    "in_production_at": null,    "awaiting_code_at": null,    "verified_at": null,    "failed_at": null,    "expired_at": null,    "canceled_at": null,    "revoked_at": null  },  "created_at": "2026-10-13T14:20:00Z"}