PortuguêsReferência da APICobrançasCriar cobrança por boleto

Criar cobrança por boleto

POST/v1/boleto
Emite um boleto bancário e retorna o link do PDF e a linha digitável.
Habilitação por conta

Boleto é liberado por conta. Se a sua ainda não estiver habilitada, a chamada retorna 400 com "Boleto não está habilitado para esta conta." — fale com o suporte para ativar. O contrato PIX (POST /v1/pix) não muda.

Request

Cabeçalhos

CabeçalhoObrigatórioDescrição
AuthorizationsimBearer <SUA_API_KEY>
Content-Typesimapplication/json

Corpo

{
  "amountCents": 5000,
  "externalRef": "pedido-123",
  "description": "Pedido 123",
  "dueDate": "2026-09-30",
  "customer": {
    "name": "Maria Silva",
    "email": "maria@exemplo.com",
    "phone": "11999998888",
    "document": {
      "number": "12345678901",
      "type": "cpf"
    },
    "address": {
      "street": "Rua das Flores",
      "number": "100",
      "complement": "Apto 12",
      "district": "Centro",
      "city": "São Paulo",
      "zipCode": "01310100",
      "state": "SP"
    }
  }
}
CampoTipoObrig.Descrição
amountCentsinteirosimValor em centavos. Mínimo: 100 (R$ 1,00). Limites por conta se aplicam.
customerobjetosimDados do pagador (ver abaixo).
customer.namestringsimNome do pagador. Máx. 100 caracteres.
customer.emailstringsimE-mail válido do pagador.
customer.phonestringcondicionalTelefone com DDD, somente números: 11 dígitos = celular, 10 = fixo. Obrigatório em contas que exigem os dados completos do pagador (ver abaixo). Nas demais é opcional e, se o provedor recusar o telefone informado, o boleto é emitido sem ele (não bloqueia a cobrança).
customer.document.numberstringsimCPF (11 dígitos) ou CNPJ (14 dígitos). Formatação é removida.
customer.document.typestringsim"cpf" ou "cnpj" (case e espaços normalizados).
customer.addressobjetocondicionalEndereço do pagador. Obrigatório em contas que exigem os dados completos do pagador; nas demais é ignorado.
customer.address.streetstringcondicionalLogradouro. Máx. 120 caracteres.
customer.address.numberstringnãoNúmero. Máx. 20 caracteres.
customer.address.complementstringnãoComplemento. Máx. 60 caracteres.
customer.address.districtstringcondicionalBairro. Máx. 60 caracteres.
customer.address.citystringcondicionalCidade. Máx. 60 caracteres.
customer.address.zipCodestringcondicionalCEP com 8 dígitos. Formatação é removida.
customer.address.statestringcondicionalUF com 2 letras, ex.: "SP".
externalRefstringnãoIdentificador no seu sistema. Usado como chave de idempotência.
descriptionstringnãoTexto livre. Máx. 200 caracteres.
dueDatestringnãoVencimento em YYYY-MM-DD, hoje ou futuro. Default: hoje + 3 dias.
Dados completos do pagador

Algumas contas exigem e-mail, telefone e endereço do pagador para emitir boleto. Nelas, faltar ou errar um desses campos retorna 400 apontando qual (ex.: "customer.address.zipCode inválido (CEP com 8 dígitos)."), sem criar a cobrança, e o vencimento precisa ser hoje ou uma data futura. Recomendamos enviar sempre os dados completos: nas contas que não exigem, o endereço é ignorado.

Idempotência via externalRef

Reenviar a mesma externalRef retorna o boleto original com "idempotent": true, sem emitir outro. Use sempre que possível, especialmente em retries de timeout. Se a emissão anterior ficou em verificação, o reenvio responde 400 com "Boleto em verificação..." até a confirmação: consulte a transação indicada na mensagem e não emita outro boleto para o mesmo pedido enquanto isso. Confirmada a emissão, o mesmo reenvio devolve o boleto (200, "idempotent": true).

Resposta 201 Created

{
  "success": true,
  "transactionId": "5glmNaIVteNioH6UBNxH",
  "status": "pending",
  "method": "boleto",
  "amountCents": 5000,
  "amount": 50,
  "dueDate": "2026-09-30",
  "bankSlipUrl": "https://southamerica-east1-coufai.cloudfunctions.net/payments-boletoPdf?tid=5glmNaIVteNioH6UBNxH&t=...",
  "identificationField": "46191110000000000000013187639011415640000005000",
  "nossoNumero": "13187639",
  "externalRef": "pedido-123",
  "idempotent": false
}
CampoDescrição
transactionIdID interno da transação. Use em GET /v1/transactions/{id}.
statusSempre "pending" na criação.
bankSlipUrlLink público do PDF do boleto, servido pela Coufai. Pode ser enviado ao pagador; não exige autenticação. Pode vir null logo após a emissão, enquanto o banco conclui o registro (normalmente menos de um minuto); consulte a transação em seguida. Em algumas contas o boleto é entregue só pela linha digitável, sem PDF: aí o bankSlipUrl fica null de forma definitiva e você deve mostrar a identificationField ao pagador.
identificationFieldLinha digitável (47 dígitos) para pagamento no internet banking. Pode vir null pelo mesmo motivo do bankSlipUrl.
nossoNumeroNúmero do boleto no banco emissor. Pode vir null, conforme o banco emissor.
dueDateVencimento aplicado.
amountCents / amountEco do valor, em centavos e em reais.

Resposta 200 OK (idempotente)

Quando externalRef já foi usada antes, a resposta é a cobrança original com "idempotent": true.

Ciclo de vida e webhooks

MomentoStatus da transaçãoEvento de webhook
Emissãopending—
Pagamento compensado pelo banco (normalmente D+1 útil)paidtransaction.paid, com netCents já descontada a taxa
Vencido sem pagamentoexpiredtransaction.expired — traz unpaidFeeCents se a sua conta tem taxa de boleto não pago

O boleto pode ser pago após o vencimento enquanto o banco aceitar; nesse caso o transaction.paid chega normalmente. O valor creditado no saldo é netCents (valor menos a taxa de boleto da sua conta). O method da transação é "boleto" em todos os eventos.

Não reconcilie por polling agressivo

Reaja ao transaction.paid e mantenha seu saldo a partir de netCents. A Coufai reconcilia pagamentos com o banco em segundo plano; um pagamento cujo aviso demorou é creditado mesmo assim.

Taxa de boleto não pago

Contas com taxa de boleto não pago configurada são cobradas quando o boleto vence sem pagamento: no momento do expired, o valor da taxa é debitado do saldo e o evento transaction.expired traz unpaidFeeCents (omitido quando não há taxa). Regras:

  • Aparece no extrato e na API como uma linha própria em GET /v1/transactions, com type: "fee", feeKind: "boleto_unpaid" e relatedTransactionId apontando para o boleto.
  • Estorno automático: se o boleto for pago depois de vencido, a taxa é devolvida junto com o crédito do pagamento — uma linha type: "fee_reversal" com o mesmo relatedTransactionId.
  • O saldo pode ficar negativo por causa da taxa. Enquanto estiver negativo, saques são recusados por saldo insuficiente; o próximo pagamento recebido abate a diferença.
  • O valor é o contratado para a sua conta — confira com o suporte. Sem taxa configurada, nada muda: o expired continua sem efeito financeiro.

Erros

HTTPerror
400"amountCents deve ser inteiro ≥ 100 (R$1,00 mínimo)."
400"customer.name obrigatório."
400"customer.document.number e customer.document.type obrigatórios."
400"customer.document.type deve ser 'cpf' ou 'cnpj'. Recebido: '<valor>'."
400"customer.email é obrigatório e deve ser válido."
400"dueDate inválido (use YYYY-MM-DD)."
400"customer.address é obrigatório para emitir boleto nesta conta." — e as variações por campo (customer.address.zipCode, customer.address.state, customer.phone…): a conta exige os dados completos do pagador; corrija o campo apontado.
400"dueDate deve ser hoje ou uma data futura (YYYY-MM-DD)."
400"Boleto em verificação: a emissão não confirmou. NÃO reenvie — consulte a transação <id> em instantes." — a emissão anterior não confirmou e o boleto pode existir; não emita outro para o mesmo pedido.
400"Dados recusados pelo provedor: <campo> inválido. Corrija e reenvie. (<código>)" — o pagador ou a cobrança foi recusado na validação do provedor. <campo> diz o que corrigir (documento, e-mail, nome, endereço, vencimento, valor); <código> é estável, ex.: invalid_cpfCnpj.
400"Limite de emissão de cobranças da conta atingido. Não reenvie; fale com o suporte. (issuance_limit)" — a conta chegou ao teto de emissão; reenviar não resolve.
400"Emissão não permitida para esta conta no momento. Não reenvie; fale com o suporte. (account_restricted)" — a conta está impedida de emitir; reenviar não resolve.
400"Boleto não está habilitado para esta conta."
400"Boleto não disponível para esta conta no momento." — habilitação em andamento; tente mais tarde ou fale com o suporte.
400"Valor acima do máximo permitido (R$ X.YY)."
401"API key inválida ou revogada."
403"Conta não está aprovada para uso da API."
429"Limite de requisições atingido. Tente em 1 hora."
500"Erro ao gerar boleto. Tente novamente."
503"Boleto temporariamente indisponível. Tente novamente em instantes." — falha passageira: nada foi emitido, pode reenviar.

Exemplos

curl -X POST https://api.coufai.com.br/v1/boleto \
  -H "Authorization: Bearer $COUFAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amountCents": 5000,
    "externalRef": "pedido-123",
    "description": "Pedido 123",
    "dueDate": "2026-09-30",
    "customer": {
      "name": "Maria Silva",
      "email": "maria@exemplo.com",
      "phone": "11999998888",
      "document": { "number": "12345678901", "type": "cpf" },
      "address": {
        "street": "Rua das Flores", "number": "100", "district": "Centro",
        "city": "São Paulo", "zipCode": "01310100", "state": "SP"
      }
    }
  }'