Documentação

Documento e área do endereço

Como enviar o PDF de uma correspondência, o que ele precisa ter e onde a CartaFlow imprime o endereço.

O conteúdo de uma correspondência é um PDF. Ele vai como arquivo, em um envio multipart, ou no campo document de um corpo JSON. A CartaFlow imprime esse conteúdo do jeito que ele está: o layout, as cores, o logo e o texto são os do seu PDF. A CartaFlow só acrescenta o endereço, na área do endereço da primeira página, e os valores das variáveis, quando você envia variáveis.

Quatro formas de enviar o PDF

FormaQuando usarComoPDF de até
Arquivo na requisiçãoVocê tem o PDF em disco ou em memória e ele é pequeno. É a forma mais simples.multipart/form-data, com o PDF na parte file.4 MB
PDF por URLO PDF já está em um armazenamento, como S3, Google Cloud Storage ou Azure.JSON, document.type: url.10 MB
Upload em duas etapasVocê tem o PDF em disco ou em memória e ele é grande.POST /v1/uploads, PUT do arquivo e JSON com document.type: upload.10 MB
PDF em base64O PDF é pequeno e você prefere mandar tudo em JSON.JSON, document.type: base64.3 MB

Por que os limites são diferentes

O corpo de uma requisição à API tem até 4,5 MB. Um PDF que vai dentro da requisição, em multipart ou em base64, precisa caber nesse limite junto com os outros campos (em base64, o arquivo fica cerca de um terço maior). Por URL ou pelo upload em duas etapas, o arquivo não passa pela requisição da API, e o limite é de 10 MB.

As quatro formas valem também para POST /v1/letters/quote, que recebe o mesmo corpo da criação.

Arquivo (multipart/form-data)

Envie o PDF na parte file, com até 4 MB, e os outros campos como partes do formulário, com os mesmos nomes do corpo JSON. Campos de objetos usam colchetes: to[name], to[postal_code], from[number], metadata[customer_id], variables[nome]. Listas repetem o campo com []: postal_services[]=registered. Booleanos vão como texto: true ou false. O campo document não existe nesta forma: o conteúdo é o arquivo.

curl -X POST "https://api.cartaflow.com.br/v1/letters" \
  -H "Authorization: Bearer $CARTAFLOW_API_KEY" \
  -H "Idempotency-Key: fatura-2026-10-0042" \
  -F "file=@fatura-2026-10-0042.pdf" \
  -F "to[name]=Destinatário Exemplo" \
  -F "to[postal_code]=01001-000" \
  -F "to[number]=128" \
  -F "to[complement]=Ap. 52" \
  -F "color=true" \
  -F "reference=fatura-2026-10-0042" \
  -F "metadata[customer_id]=1842"

A resposta é a mesma da criação em JSON. Em document, a correspondência informa a forma usada: { "type": "upload", "filename": "fatura-2026-10-0042.pdf" }.

PDF por URL

A CartaFlow baixa o arquivo uma única vez, no momento da criação. A URL precisa ser HTTPS, pública ou assinada, e continuar válida por pelo menos 10 minutos. Esperamos até 10 segundos pelo download. O arquivo pode ter até 10 MB.

"document": {
  "type": "url",
  "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf"
}

Upload em duas etapas

Para um PDF de até 10 MB que está com você, mas não cabe numa requisição, envie o arquivo antes e depois crie a correspondência:

  1. Crie um upload com POST /v1/uploads, informando o nome (filename) e o tamanho em bytes (size) do arquivo. A resposta traz o id do upload, que começa com upl_, e um upload_url assinado.
  2. Envie o arquivo com PUT para o upload_url: os bytes do PDF no corpo, o cabeçalho Content-Type: application/pdf e sem o cabeçalho Authorization, porque a assinatura já está na URL. O link vale por 2 horas. Uma resposta 2xx confirma que o arquivo chegou.
  3. Crie a correspondência com document: { "type": "upload", "upload_id": "upl_..." }, em até 24 horas depois de criar o upload.
# Este exemplo usa jq para ler o JSON da resposta.
SIZE=$(wc -c < fatura-2026-10-0042.pdf | tr -d ' ')

# 1. Crie o upload com o nome e o tamanho do arquivo.
UPLOAD=$(curl -s -X POST "https://api.cartaflow.com.br/v1/uploads" \
  -H "Authorization: Bearer $CARTAFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{ \"filename\": \"fatura-2026-10-0042.pdf\", \"size\": $SIZE }")

UPLOAD_ID=$(echo "$UPLOAD" | jq -r .id)
UPLOAD_URL=$(echo "$UPLOAD" | jq -r .upload_url)

# 2. Envie o arquivo para o upload_url, sem o cabeçalho Authorization.
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: application/pdf" \
  --data-binary "@fatura-2026-10-0042.pdf"

# 3. Crie a correspondência com o upload.
curl -X POST "https://api.cartaflow.com.br/v1/letters" \
  -H "Authorization: Bearer $CARTAFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: fatura-2026-10-0042" \
  -d "{
    \"to\": { \"name\": \"Destinatário Exemplo\", \"postal_code\": \"01001-000\", \"number\": \"128\" },
    \"document\": { \"type\": \"upload\", \"upload_id\": \"$UPLOAD_ID\" },
    \"reference\": \"fatura-2026-10-0042\"
  }"

Regras do upload:

  • Uma correspondência por upload. Depois que uma correspondência é criada com ele, o upload não serve para outra: a API responde 422 com upload_already_used. Para repetir a mesma criação com segurança, use a mesma Idempotency-Key.
  • Simular não consome o upload. Você pode usar o mesmo upload_id em POST /v1/letters/quote quantas vezes quiser antes de criar a correspondência. Uma criação recusada, como um 422, também não consome o upload.
  • Prazos. O upload_url aceita o arquivo por 2 horas (upload_url_expires_at). O upload pode ser usado por 24 horas (expires_at); depois disso, a API responde upload_expired.
  • O arquivo precisa ter chegado. Se você criar a correspondência sem ter enviado o arquivo, a API responde upload_file_missing.
  • O arquivo é conferido na criação, com as mesmas regras de qualquer PDF: A4, sem senha, área do endereço em branco, até 6 folhas.
  • Variáveis funcionam igual: envie variables dentro de document, junto com upload_id.
  • O upload é da sua conta. Um upload_id de outra conta recebe upload_not_found.

Na correspondência criada, document traz { "type": "upload", "filename": "fatura-2026-10-0042.pdf" }, igual a um envio em multipart.

PDF em base64

O PDF vai dentro do corpo JSON, em base64 padrão, sem o prefixo data:application/pdf;base64,. O arquivo pode ter até 3 MB depois de decodificado (cerca de 4 MB em base64), para que o corpo inteiro caiba nos 4,5 MB da requisição. Para PDFs maiores, use URL ou o upload em duas etapas.

PDF=$(base64 < contrato-5531.pdf | tr -d '\n')

curl -X POST "https://api.cartaflow.com.br/v1/letters" \
  -H "Authorization: Bearer $CARTAFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: contrato-5531" \
  -d "{
    \"to\": { \"name\": \"Destinatário Exemplo\", \"postal_code\": \"01001-000\", \"number\": \"128\" },
    \"document\": { \"type\": \"base64\", \"data\": \"$PDF\" },
    \"double_sided\": true,
    \"reference\": \"contrato-5531\"
  }"

Variáveis dentro de um PDF

Um PDF pode ter marcações de variáveis, como {{nome}} ou {{valor_total}}. É o jeito mais simples de personalizar um documento feito no Word ou em outro editor: escreva a marcação no texto, exporte em PDF e envie as variáveis junto.

Trecho do documento no Word
Olá, {{nome}}.
Sua fatura de {{mes}} vence em {{vencimento}}.

A CartaFlow escreve cada valor no lugar da sua marcação, com o mesmo tamanho e a mesma cor, e o resto da linha se ajusta ao valor, como se ele tivesse sido digitado ali: sem buracos quando o valor é curto e sem sobreposição quando é longo. Uma linha centralizada continua centralizada, e o texto depois de uma tabulação e as outras linhas não saem do lugar. O valor não quebra linha: quando ele não cabe, o resto da linha é apertado um pouco, até 85% da largura, e, se ainda assim não couber, passa da margem. Isso nunca impede o envio; confira o resultado no preview_url da correspondência ou na prévia do painel.

  • Em JSON, envie variables dentro de document, com type: url, type: upload ou type: base64.
  • Em multipart, envie uma parte por variável: variables[nome], variables[mes].
  • Nomes usam letras, números e sublinhado. Valores são textos ou números.
  • Sem variables, o PDF é impresso como está.
JSON
"document": {
  "type": "url",
  "url": "https://arquivos.exemplo.com.br/faturas/modelo-fatura.pdf",
  "variables": {
    "nome": "Destinatário Exemplo",
    "mes": "outubro",
    "vencimento": "20/10/2026"
  }
}
Multipart
curl -X POST "https://api.cartaflow.com.br/v1/letters" \
  -H "Authorization: Bearer $CARTAFLOW_API_KEY" \
  -F "file=@modelo-fatura.pdf" \
  -F "to[name]=Destinatário Exemplo" \
  -F "to[postal_code]=01001-000" \
  -F "to[number]=128" \
  -F "variables[nome]=Destinatário Exemplo" \
  -F "variables[mes]=outubro" \
  -F "variables[vencimento]=20/10/2026"

A conferência é rigorosa nos dois sentidos, para que nenhum documento saia com uma marcação esquecida:

SituaçãoResposta
O documento tem uma marcação que não veio em variables.422 variable_missing
Você enviou uma variável que o documento não tem.422 variable_not_found
O PDF não tem texto selecionável: é uma imagem ou uma digitalização.422 document_text_unreadable

Exporte o PDF direto do editor

No Word, use Arquivo > Salvar como > PDF. Digitalizar ou imprimir em PDF a partir de uma imagem gera um PDF sem texto, e a API não encontra as marcações. Para conferir as marcações sem custo, faça uma simulação com POST /v1/letters/quote com as mesmas variables.

Numa verificação de endereço com o seu próprio PDF, {{OTP_CODE}}, {{VERIFICATION_URL}} e {{QR_CODE}} são marcações reservadas, preenchidas pela CartaFlow com o código e o acesso à página de confirmação. Veja O seu próprio PDF.

O que o PDF precisa ter

  • Tamanho A4 em retrato (210 x 297 mm) em todas as páginas.
  • Dentro do limite da forma de envio: 10 MB por URL ou upload em duas etapas, 4 MB em multipart e 3 MB em base64. Imagens a 300 dpi são o máximo que a impressão aproveita.
  • Até 6 folhas por correspondência, contando a folha que o endereço às vezes acrescenta. É o que cabe em um envelope.
  • Sem senha e sem restrições de impressão.
  • Fontes incorporadas. Exporte o PDF com as fontes embutidas para que o texto saia igual ao que você vê na tela.
  • Margem de segurança. Mantenha textos e elementos importantes a pelo menos 5 mm das bordas.
  • Área do endereço em branco na primeira página, quando address_placement é first_page.

A área do endereço

O envelope tem uma janela. Pela janela aparece um retângulo da primeira página: a área do endereço. A CartaFlow imprime ali o remetente, em uma linha, e o destinatário logo abaixo. Por isso essa área precisa estar em branco no seu PDF.

Área do endereço na primeira páginaUma página A4, de 210 por 297 mm. A área do endereço tem 90 por 45 mm e fica a 20 mm da borda esquerda e a 45 mm da borda de cima.Área do endereçoDeixe em branco: a CartaFlowimprime aqui o remetentee o destinatário.20 mm45 mm90 mm45 mmA4 · 210 x 297 mm
A linha tracejada é a margem de segurança: mantenha textos e elementos importantes a pelo menos 5 mm das bordas.

Se o seu layout ocupa essa área, por exemplo porque a primeira página de uma fatura já tem outro conteúdo ali, use address_placement: extra_page.

address_placementOnde o endereço é impressoCusto
first_page (padrão)Na área do endereço da primeira página do seu documento.Sem acréscimo.
extra_pageNum lado só dele, o primeiro, que aparece pela janela, com o remetente e o destinatário. Ele ocupa um lado que ficaria em branco, quando há um; se não há, entra uma folha a mais no início. O seu documento vem em seguida.Sem acréscimo, mesmo quando entra uma folha a mais.

Quando a área do endereço não está em branco e address_placement é first_page, a API responde 422 com o código address_area_not_blank, e nada é criado nem cobrado.

Cor e frente e verso

  • color: true imprime em cores. Com false, o padrão, a impressão é em preto e branco, e um PDF colorido sai em tons de cinza. A impressão colorida tem acréscimo por página impressa: cada lado impresso de uma folha conta como uma página.
  • double_sided: true imprime frente e verso: cada folha leva duas páginas do documento. A correspondência usa menos folhas e custa menos. Com false, o padrão, cada página vai em uma folha.

Quantas folhas uma correspondência usa

O campo sheets diz quantas folhas de papel vão no envelope. O preço conta só as folhas do seu documento: o endereço nunca é cobrado, mesmo quando acrescenta uma folha.

  • Só frente: uma folha por página.
  • Frente e verso: metade das páginas, arredondada para cima.
  • Com extra_page, só frente: o mesmo número de folhas. O endereço vai no verso da primeira página, e só essa folha é impressa dos dois lados.
  • Com extra_page, frente e verso, número ímpar de páginas: o mesmo número de folhas. O endereço usa o lado que sobra.
  • Com extra_page, frente e verso, número par de páginas: mais uma folha, só com o endereço e o verso em branco.
Páginas do PDFdouble_sidedaddress_placementsheets
1falsefirst_page1
3falsefirst_page3
3truefirst_page2
2falseextra_page2
7trueextra_page4
2trueextra_page2: a folha do endereço não é cobrada
7falsefirst_page7: passa do limite, too_many_sheets
12trueextra_page7: passa do limite, too_many_sheets

Com color: true, a linha color do preço conta páginas, não folhas: cada lado impresso é uma página. Um PDF de 3 páginas em frente e verso usa 2 folhas e 3 páginas coloridas. O lado do endereço nunca é colorido nem cobrado.

Quando a correspondência passaria de 6 folhas, contando a folha que o endereço acrescenta, a API responde 422 com o código too_many_sheets. Use double_sided: true ou divida o conteúdo em mais de uma correspondência.

Confira o resultado antes de enviar

  • Simulação. POST /v1/letters/quote recebe exatamente o mesmo corpo da criação, valida o documento e as variáveis, conta as páginas e devolve o preço e o endereço completo. Nada é criado nem cobrado.
  • PDF final. Toda correspondência traz em preview_url um link para o PDF exatamente como será impresso, já com o endereço. O link vale por 60 minutos; consulte a correspondência de novo para receber um link novo. O arquivo fica disponível por pelo menos 90 dias depois da criação (ou depois da data do envio, numa correspondência agendada).

Numa correspondência em preto e branco, o preview_url mostra as cores do PDF original: a conversão para tons de cinza acontece na impressão.

Enquanto a correspondência estiver em received (ou em scheduled, se foi agendada), você ainda pode cancelar: nada é impresso e, se ela já foi cobrada, o valor volta para o saldo. Veja Correspondências e status.

Erros de documento

Quando o documento tem um problema, a API responde 422 com validation_error, e cada item de details aponta o campo e o motivo. Nada é criado nem cobrado.

details[].codeO que aconteceu
document_unreachableNão conseguimos baixar o PDF da URL a tempo, ou o servidor respondeu com erro.
upload_not_foundNão existe upload com esse upload_id na sua conta.
upload_expiredO upload foi criado há mais de 24 horas.
upload_already_usedO upload já foi usado por outra correspondência.
upload_file_missingO arquivo nunca foi enviado para o upload_url.
document_invalidO arquivo não é um PDF válido. Em base64, confira se não há o prefixo data:.
document_encryptedO PDF tem senha.
document_too_largeO PDF passa do limite da forma de envio: 10 MB por URL ou upload, 4 MB em multipart, 3 MB em base64.
document_page_sizeAlguma página não é A4 em retrato.
too_many_sheetsA correspondência passaria de 6 folhas.
address_area_not_blankHá conteúdo na área do endereço da primeira página.
document_text_unreadableVocê enviou variables, mas o PDF não tem texto selecionável.
variable_missingO documento tem uma marcação que não veio em variables.
variable_not_foundVocê enviou uma variável que o documento não tem.

Um corpo maior que 4,5 MB nem chega a ser lido: a API responde 413 com request_too_large. A lista completa de códigos está em Erros.

Nesta página