Verificação de endereço físico
Confirme que uma pessoa recebe correspondência no endereço que informou, com uma correspondência com código e a sua marca.
A verificação de endereço físico confirma que uma pessoa recebe correspondência no endereço que ela informou. A CartaFlow envia para esse endereço uma correspondência com um código de 6 dígitos. Quando a pessoa confirma o código, o endereço fica verificado: só quem recebeu a correspondência conhece o código.
Por exemplo, uma fintech recebe um pedido de abertura de conta e pede a verificação do endereço informado. Quando a correspondência chega, o cliente vê o logo da fintech, escaneia o QR code e confirma. O cadastro passa a ter o endereço verificado.
A correspondência leva a sua marca
A correspondência de verificação sai em nome da sua empresa. Nem a correspondência nem a página de confirmação mostram o nome ou o logo da CartaFlow. Por enquanto, a página fica no domínio verifica.cartaflow.com.br, num endereço com o id da sua conta (é o link impresso na correspondência e o que o QR code abre); páginas no domínio da sua empresa podem vir depois. A página e o modelo da CartaFlow usam o seu logo e o nome fantasia da sua empresa (a razão social, quando não há nome fantasia). Configure os dois no painel, em Configurações > Empresa, antes da primeira verificação. No seu próprio PDF, a correspondência leva o layout e a marca do seu documento.
A correspondência pode sair de duas formas:
| Forma | Quando usar | Preço |
|---|---|---|
| Modelo da CartaFlow (padrão) | Você quer uma correspondência pronta, com o seu logo e os seus textos. | Um envio simples do seu plano. |
| O seu próprio PDF | Você já tem um layout, como um documento do Word, e quer só incluir o código. | O de uma correspondência com as mesmas opções. |
Nas duas formas, a correspondência traz o código de 6 dígitos e, com method: hosted_page, pode trazer o QR code e o endereço da página de confirmação.
Três formas de usar
| Forma | Como a pessoa confirma | O que você constrói |
|---|---|---|
| Pelo painel | Na página com a sua marca, pelo QR code. | Nada. Você pede as verificações no painel e acompanha o resultado ali. |
API com method: hosted_page | Escaneia o QR code e confirma em uma página com a sua marca, hospedada pela CartaFlow. | A chamada que cria a verificação e um webhook para saber o resultado. |
API com method: code | Digita o código no seu site ou aplicativo. | A tela onde a pessoa digita o código e a chamada que confere o código. |
Com hosted_page, o endereço da página fica em hosted_page_url. Você também pode mandar esse link por e-mail ou mostrar no seu app. Depois de confirmar, a página mostra um botão que leva a pessoa para return_url, se você enviou um.
O campo source diz por onde cada verificação foi criada: api ou dashboard. Ele não depende de como a pessoa confirma, que fica em confirmation. Por exemplo, uma verificação criada no painel é confirmada na página, e uma criada pela API com method: hosted_page pode ser confirmada na página ou conferida pelo seu servidor.
Criar uma verificação
No endereço, só name, postal_code e number são obrigatórios. O resto é preenchido a partir do CEP quando você não envia, como nas correspondências. Veja Endereços no Brasil.
curl -X POST "https://api.cartaflow.com.br/v1/verifications" \
-H "Authorization: Bearer $CARTAFLOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: verificacao-cliente-1842" \
-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"
}'A resposta tem status received, source: "api" e attempts_remaining igual a 5. Sem letter nem document, a correspondência sai do modelo da CartaFlow, com os textos do modelo padrão da sua empresa. Com method: code, troque return_url por instructions, por exemplo "Abra o app, vá em Perfil > Endereço e digite o código.". Se você não enviar instructions, imprimimos um texto padrão com o nome da sua empresa.
Ninguém vê o código, nem você
Nem a API nem o painel mostram o código, para ninguém da sua empresa. Ele só existe na correspondência que a CartaFlow imprime, e é isso que prova o endereço. preview_url traz a correspondência como ela será impressa, com o endereço, mas com o código escondido: no lugar dele aparece 000 000, e no lugar do QR code, um quadro que mostra onde ele será impresso.
Modelo da CartaFlow
Sem document, a CartaFlow monta a correspondência: uma folha A4 em preto e branco com o seu logo, o nome da sua empresa, o endereço na janela do envelope, um título, um texto, o código e um rodapé. Com method: hosted_page, ela traz também o QR code, que abre a página já com o código, e o endereço da página, para quem prefere digitar.
O que vai impresso vem de três camadas, nesta ordem:
- O padrão da CartaFlow.
- O modelo padrão da sua empresa, salvo no painel. Vale para todas as verificações, criadas pela API ou pelo painel.
- O campo
letterda requisição, só para esta verificação.
Cada campo que você não envia em letter vem da camada anterior.
Campo de letter | O que é | Padrão da CartaFlow |
|---|---|---|
title | O título, em destaque. Até 80 caracteres. | Confirme o seu endereço |
body | O texto antes do código. Até 1.200 caracteres. | {{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar. |
footer | O texto do pé da página. Até 300 caracteres. | 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 | Imprime o QR code que abre a página já com o código. | true |
include_page_url | Imprime o endereço da página de confirmação, para a pessoa abrir no navegador e digitar o código. | true |
Nos textos, você pode usar duas marcações: {{empresa}}, que vira o nome da sua empresa, e {{nome}}, que vira o nome do destinatário (to.name). Qualquer outra marcação entre chaves dá 422 com invalid_value.
{
"to": { "name": "Destinatário Exemplo", "postal_code": "01001-000", "number": "128" },
"method": "hosted_page",
"letter": {
"title": "Confirme seu endereço, {{nome}}",
"body": "{{empresa}} precisa confirmar o endereço do seu cadastro. Use o código abaixo.",
"include_page_url": false
}
}- Com
method: code, o QR code e o endereço da página nunca são impressos, mesmo cominclude_qr_codeouinclude_page_urlemtrue. No lugar deles vai o texto deinstructions. - O modelo usa sempre uma folha em preto e branco.
color,double_sidedeaddress_placementsó valem com o seu próprio PDF. - A resposta traz em
documento que foi usado, comtype: "template"e os textos ainda com as marcações.
O seu próprio PDF
Envie o seu PDF em document, como numa correspondência: type: url, type: upload ou type: base64. Este endpoint aceita só JSON: para enviar o arquivo, use o upload em duas etapas. O PDF segue as regras de uma correspondência: A4 em retrato, até 6 folhas, texto selecionável e a área do endereço em branco, ou address_placement: extra_page. Veja Documento e área do endereço.
Escreva no documento as marcações que a CartaFlow preenche:
| Marcação | Obrigatória | O que a CartaFlow imprime no lugar |
|---|---|---|
{{OTP_CODE}} | Sim. Sem ela, a API responde 422 com otp_code_missing. | O código, no formato 123 456, com a fonte, o tamanho e a cor da marcação. |
{{VERIFICATION_URL}} | Não. Só com method: hosted_page. | O endereço da página de confirmação, o mesmo de hosted_page_url, sem o código. |
{{QR_CODE}} | Não. Só com method: hosted_page. | Um QR code de 25 x 25 mm que abre a página já com o código. O canto superior esquerdo fica onde começa a marcação. |
- Escreva as marcações em maiúsculas e com as chaves, como na tabela.
- Deixe espaço depois de
{{OTP_CODE}}para o código inteiro e, a partir de{{QR_CODE}}, um quadrado em branco de 25 mm para a direita e para baixo. - Com
method: code,{{VERIFICATION_URL}}e{{QR_CODE}}dão 422 cominvalid_value. Escreva no documento onde a pessoa digita o código. - As outras marcações, como
{{nome}}, são variáveis comuns: envie os valores emdocument.variables. Não envie valores para as marcações reservadas: a API respondevariable_not_found. color,double_sidedeaddress_placementfuncionam como numa correspondência e entram no preço.instructionsnão é impresso no seu PDF.
{
"to": { "name": "Destinatário Exemplo", "postal_code": "01001-000", "number": "128" },
"method": "hosted_page",
"document": {
"type": "upload",
"upload_id": "upl_6Np3Vx8Rk2Tq",
"variables": { "nome": "Destinatário Exemplo" }
},
"color": true,
"reference": "cliente-2210"
}A resposta traz em document a forma de envio (upload, url ou base64) e as variables que você enviou.
Confira a correspondência logo depois de criar
Abra preview_url assim que a verificação for criada. Enquanto ela está em received, você pode cancelar e o valor volta para o saldo.
Status
- Recebida
received- Cancelada
canceled
- Cancelada
- Em produção
in_production- Cancelada
canceled - Revogada
revoked
- Cancelada
- Aguardando código
awaiting_code- Falhou
failed - Expirada
expired - Revogada
revoked
- Falhou
- Verificada
verified- Revogada
revoked
- Revogada
| Status | O que significa | Final | Cancelável |
|---|---|---|---|
receivedRecebida | A CartaFlow recebeu o pedido, cobrou o preço do seu saldo e colocou a correspondência com o código na fila de produção. Se você cancelar agora, nada é impresso e o valor volta para o saldo. | Não | Sim |
in_productionEm produção | A correspondência com o código está sendo impressa e envelopada. Cancelar agora revoga a verificação (revoked), sem devolução do valor. | Não | Sim |
awaiting_codeAguardando código | A correspondência foi postada. Agora esperamos a pessoa confirmar o código. Ela tem 60 dias a partir da postagem (veja expires_at). Cancelar agora revoga a verificação, sem devolução do valor. | Não | Sim |
verifiedVerificada | A pessoa confirmou o código certo. Ela recebe correspondência no endereço informado. confirmation diz como e quando. Você ainda pode revogar a verificação, e ela passa para revoked. | Não | Sim |
failedFalhou | Foram digitados 5 códigos errados. A verificação foi bloqueada para impedir tentativas aleatórias. Crie uma nova verificação se quiser tentar de novo. | Sim | Não |
expiredExpirada | Passaram 60 dias desde a postagem sem que a pessoa confirmasse o código. | Sim | Não |
canceledCancelada | A verificação foi cancelada antes da postagem e o valor voltou para o seu saldo. Ou você cancelou enquanto ela estava em received, ou a CartaFlow cancelou porque a correspondência não pôde ser produzida. | Sim | Não |
revokedRevogada | Você cancelou a verificação depois que a produção começou: em produção, aguardando código ou já verificada. O valor não volta para o saldo, porque a produção já começou, e uma correspondência que estava em produção ainda é postada. O código deixa de funcionar, na página e na API, e a verificação nunca mais aparece como verified. | Sim | Não |
O código só pode ser confirmado em awaiting_code, depois da postagem. A pessoa tem 60 dias a partir da postagem para confirmar. O prazo exato fica em expires_at. Depois dele, a verificação vai para expired.
verified não é o fim: se você revogar a verificação, ela passa para revoked. Trate um endereço como verificado só enquanto o status for verified.
Conferir o código digitado no seu app
Com method: code, a pessoa digita o código no seu site ou app, e o seu servidor confere com POST /v1/verifications/{verification_id}/check. Faça essa chamada sempre do servidor, nunca do navegador ou do app.
curl -X POST "https://api.cartaflow.com.br/v1/verifications/ver_8Wn2Rt6Yk4Js/check" \
-H "Authorization: Bearer $CARTAFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "code": "482917" }'Um código errado não é um erro da API. A resposta é sempre 200, com correct: false, e attempts_remaining diminui. Depois de 5 códigos errados, contando os digitados na página e pela API, a verificação vai para failed. Para tentar de novo, crie uma verificação nova.
Respostas de erro só acontecem quando a conferência não faz sentido no momento:
| Situação | Resposta |
|---|---|
A correspondência ainda não foi postada, ou a verificação já terminou (verified, failed, expired, canceled, revoked). | 409 com verification_not_awaiting_code. A mensagem informa o status atual. |
| O código não tem 6 dígitos. | 422 com invalid_format em code. Essa tentativa não é contada. |
A tela onde a pessoa digita o código
Algumas escolhas deixam a confirmação mais fácil:
- Use um campo numérico (
inputmode="numeric"eautocomplete="one-time-code") para 6 dígitos. - Aceite o código com espaços ou traços e remova esses caracteres antes de enviar.
- Depois de um erro, diga quantas tentativas restam.
- Quando a verificação estiver em
failedouexpired, explique o que aconteceu e ofereça pedir uma nova correspondência.
Sugestões de mensagens:
| Situação | Mensagem |
|---|---|
| Código certo | Endereço confirmado. Obrigado. |
| Código errado | Este código não confere. Você ainda tem 3 tentativas. |
| Última tentativa | Este código não confere. Você tem mais 1 tentativa. |
Sem tentativas (failed) | Não foi possível confirmar o endereço com este código. Peça uma nova correspondência de verificação. |
Prazo vencido (expired) | O prazo para confirmar este código terminou. Peça uma nova correspondência de verificação. |
| Ainda não postada (409) | A correspondência com o código ainda está a caminho. Tente quando ela chegar. |
| Cancelada ou revogada (409) | Esta verificação foi cancelada. Se você esperava confirmar o seu endereço, fale com a gente. |
Como a confirmação foi feita
Quando o código certo é confirmado, a verificação passa a ter confirmation. Antes disso, confirmation é null.
"confirmation": {
"method": "hosted_page",
"hosted_page_entry": "qr_code",
"confirmed_at": "2026-10-21T19:32:00Z",
"ip": "198.51.100.23",
"location": { "city": "São Paulo", "region": "SP", "country": "BR", "postal_code": "01000", "latitude": -23.5475, "longitude": -46.6361 },
"user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
"device": { "type": "mobile", "os": { "name": "iOS", "version": "17.5" }, "browser": { "name": "Safari", "version": "17.5" } },
"client": { "language": "pt-BR", "accept_language": "pt-BR,pt;q=0.9", "timezone": "America/Sao_Paulo", "screen": { "width": 390, "height": 844, "pixel_ratio": 3 }, "time_on_page_ms": 8100 },
"precise_location": {
"latitude": -23.5489, "longitude": -46.6388, "accuracy_m": 14.5, "distance_m": 606,
"shared_at": "2026-10-21T19:32:40Z", "ip": "198.51.100.23",
"user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
"address_coordinates": { "latitude": -23.5503898, "longitude": -46.633081 }
}
}| Campo | O que é |
|---|---|
method | hosted_page, quando a pessoa confirmou na página, ou api, quando o seu servidor conferiu o código com /check. |
hosted_page_entry | Na página: qr_code, quando a pessoa escaneou o QR code, ou typed, quando digitou o código. null com method: api. |
confirmed_at | Quando o código certo foi confirmado. |
ip | O IP de onde veio a confirmação. Na página, é o do aparelho da pessoa. Pela API, é o do seu servidor, não o da pessoa. |
location | Cidade, região (no Brasil, a UF), país, código postal, latitude e longitude, estimados a partir do IP. Só na página; null pela API. |
user_agent | O user agent do navegador que confirmou. Pela API, o do seu servidor. |
device | Tipo de aparelho (mobile, tablet ou desktop), sistema e navegador, com as versões, lidos do user_agent. |
client | O idioma do navegador, o cabeçalho Accept-Language, o fuso horário, a tela e quanto tempo passou entre abrir a página e enviar o código. Pela API, só accept_language, quando o seu servidor envia. |
precise_location | A localização do aparelho, só quando a pessoa escolhe compartilhar depois de confirmar (veja Localização opcional), com a distância até o CEP do endereço. |
Cada campo que não pôde ser registrado vem null. Confirmações registradas antes de 14/10/2026 têm null em user_agent, device, client e precise_location.
IP, localização e aparelho são indícios
São registrados quando estão disponíveis e podem vir null. location vem da rede, não do GPS: uma rede móvel, uma VPN ou um proxy podem indicar outra cidade ou outro país. device e client vêm do que o navegador informa. Use tudo isso como indícios a mais numa análise de fraude, nunca como prova do endereço. A prova é o código, que só chega pela correspondência.
Uma verificação revogada depois de confirmada mantém confirmation e status_transitions.verified_at como registro, mas o status é revoked.
A página de confirmação
Com method: hosted_page, a CartaFlow hospeda a página onde a pessoa confirma, com o seu logo e o nome da sua empresa, e nada da CartaFlow: nem nome, nem logo, nem cores. O endereço é https://verifica.cartaflow.com.br/{id da sua conta}/{token da página}, o mesmo de hosted_page_url. Use o valor de hosted_page_url como veio, sem montar o endereço por conta própria.
O que a pessoa vê:
- O seu logo e o nome fantasia da sua empresa (a razão social, quando não há nome fantasia).
- Pelo QR code, a página abre com o código já preenchido: a pessoa toca uma vez em Confirmar endereço. Abrir o link nunca confirma sozinho.
- Pelo endereço impresso, ou por
hosted_page_urlenviado por você, a pessoa digita os 6 dígitos. - O resultado: endereço confirmado, ou código errado com as tentativas que restam.
- Depois de confirmar, um botão para
return_url, se você enviou um, e a opção de compartilhar a localização. - Um aviso curto sobre o que é registrado para comprovar a confirmação e quem é responsável pelos dados.
- O contato da sua empresa, quando configurado (abaixo).
A página é em português, funciona no celular e no computador, não é indexada por buscadores e não tem ferramentas de análise nem scripts de terceiros.
Quando a verificação não espera mais código, a página não aceita códigos e explica o motivo, citando a sua empresa e o seu contato:
| Status | O que a página diz |
|---|---|
received, in_production | A correspondência com o código ainda não foi postada. |
verified | O endereço já foi confirmado. |
failed | O código foi bloqueado depois de 5 tentativas erradas. A pessoa deve falar com a sua empresa para receber uma nova correspondência. |
expired | O prazo para confirmar terminou. A pessoa deve falar com a sua empresa para receber um novo código. |
canceled, revoked | A verificação foi cancelada pela sua empresa. Se a pessoa esperava confirmar o endereço, deve falar com a sua empresa. |
Prepare o seu atendimento para esses contatos.
O seu contato na página
Em Configurações > Empresa, você pode informar o site, o e-mail, o telefone e o endereço da política de privacidade da sua empresa. Todos são opcionais. A página mostra o que estiver preenchido, inclusive nas mensagens que pedem para a pessoa falar com a sua empresa, e o link da política de privacidade fica no aviso sobre os dados.
O que a página registra
Em cada tentativa, certa ou errada, a página registra: data e hora, IP, localização aproximada do IP, user agent, aparelho, sistema e navegador, idioma, fuso horário, tela, quanto tempo a pessoa ficou na página e se o código veio do QR code ou foi digitado. Tudo aparece no painel, no detalhe da verificação, e a confirmação aparece na API, em confirmation. Por enquanto, não é possível desligar nenhum desses registros.
Contra tentativas automáticas, além do limite de 5 códigos errados por verificação, a página limita as tentativas e as consultas por IP.
Localização opcional
Depois de confirmar o código, a página oferece "Compartilhar minha localização". Se a pessoa tocar e o navegador tiver permissão, a página envia a posição do aparelho, com a precisão informada por ele. Ela nunca é pedida antes do código, nunca é obrigatória e só é aceita uma vez, até 30 minutos depois da confirmação.
A localização fica em confirmation.precise_location, com a distância em metros até as coordenadas do CEP do endereço (distance_m). O CEP marca uma rua ou um trecho dela, não o número da casa, então uma distância de algumas centenas de metros é normal. distance_m vem null quando não temos as coordenadas desse CEP.
Acompanhar pelo webhook
O evento mais importante é verification.verified. Com method: hosted_page, é por ele que o seu sistema fica sabendo da confirmação, e data.confirmation diz como ela foi feita. Trate também verification.revoked: uma verificação revogada não conta mais como verificada, mesmo que tenha sido confirmada antes. Nos eventos, preview_url vem null: consulte a verificação para receber o link. Veja Webhooks.
| Evento | Quando é enviado |
|---|---|
verification.received | Uma verificação foi criada, pela API ou pelo painel (veja source), e a correspondência com o código está na fila de produção. |
verification.in_production | A correspondência com o código está sendo impressa. A partir daqui, cancelar revoga a verificação, sem devolução. |
verification.awaiting_code | A correspondência com o código foi postada. A pessoa já pode confirmar quando receber. |
verification.verified | A pessoa confirmou o código certo. O endereço está verificado. |
verification.failed | Foram digitados 5 códigos errados e a verificação foi bloqueada. |
verification.expired | A pessoa não confirmou o código em 60 dias desde a postagem. |
verification.canceled | A verificação foi cancelada antes da postagem, por você ou pela CartaFlow, e o valor voltou para o saldo. |
verification.revoked | Você cancelou a verificação depois que a produção começou. O código deixou de funcionar e o valor não volta para o saldo. Se ela estava verified, trate o endereço como não verificado. |
Preço
Com o modelo da CartaFlow, cada verificação custa o mesmo que um envio simples do seu plano: uma linha base em price. Com o seu PDF, o preço é o de uma correspondência com as mesmas opções: base, mais additional_sheets e color quando se aplicam. Uma verificação vai sempre como carta simples, sem serviços dos Correios. O valor é debitado do saldo na criação. Veja Preços e saldo.
Cancelar ou revogar
POST /v1/verifications/{verification_id}/cancel cancela ou revoga a verificação, conforme o status. O painel faz o mesmo, com as mesmas regras.
| Status | Resultado | Valor |
|---|---|---|
received | canceled: nada é impresso. | Volta para o saldo. |
in_production, awaiting_code ou verified | revoked: o código deixa de funcionar, na página e na API, e a verificação nunca mais aparece como verified. | Não volta. |
canceled ou revoked | Nada muda: a resposta traz a mesma verificação. | |
failed ou expired | 409 com verification_not_cancelable. |
Revogue quando o endereço não deve mais contar como verificado, por exemplo quando o cadastro foi encerrado ou você suspeita de fraude. Revogar não impede a entrega: uma correspondência que já estava em produção ainda é postada, e quem tentar confirmar o código vê o aviso para falar com a sua empresa.
Uma verificação também pode ir para canceled sem pedido seu, quando a correspondência não pode ser produzida. Nesse caso, o valor volta para o saldo automaticamente.
Use com consentimento
Peça a verificação só para um endereço que a própria pessoa informou a você, e diga a ela que uma correspondência com um código vai chegar. A correspondência é uma comunicação da sua empresa com o seu cliente.
A sua empresa é a responsável pelos dados registrados na confirmação, e a página diz isso à pessoa. Informe em Configurações > Empresa o endereço da sua política de privacidade, para que ela apareça na página.