API v1
Integre o Capflux ao seu ERP ou sistema: envie documentos, puxe a fila pronta para lançar, confirme o lançamento, informe o pagamento, sincronize fornecedores e consulte cards para BI.
Ambiente de testes: captura.bsph.com.br/v1, empresa Sandbox, sem garantia de disponibilidade.
- Endereço:
https://api.capflux.com.br - Autenticação: cabeçalho
Authorization: Bearer <chave>. A chave é criada pelo administrador em Configurações › Integrações, só enxerga a própria empresa e aparece uma vez. - Idempotência: toda escrita leva
Idempotency-Key. Repetir com a mesma chave e o mesmo corpo devolve a mesma resposta, sem duplicar. - Limite: 60 chamadas por minuto no Essencial e 300 no Profissional, por chave. Passou:
429comRetry-After. - Erros:
{ "erro": { "codigo", "mensagem", "campo" } }, em português. - Versão:
/v1. Mudança que quebra compatibilidade só em/v2, com aviso e prazo. - Especificação: openapi.json (OpenAPI 3.1).
Endereços
- Testar a chave GET /v1/eu
- Enviar documentos (nota, boleto, anexos) POST /v1/documentos
- Situação de um documento enviado GET /v1/documentos/{id}
- Notas aprovadas para lançar · consultar cards GET /v1/cards
- Criar pedido de pagamento sem nota POST /v1/pedidos-pagamento
- Sincronizar um fornecedor PUT /v1/fornecedores/{cnpj_cpf}
- Um card GET /v1/cards/{id}
- Baixar um arquivo do card GET /v1/arquivos/{id}
- Confirmar o lançamento no ERP POST /v1/cards/{id}/lancamento
- Informar o pagamento POST /v1/cards/{id}/pagamento
GET/v1/eu
Testar a chave
Mostra a empresa, os escopos e o limite por minuto da chave.
Respostas
200 | Chave válida. |
401 | Chave ausente, inválida, revogada ou vencida. |
429 | Limite de chamadas por minuto da chave (60 no Essencial, 300 no Profissional). Veja Retry-After. |
curl
curl https://api.capflux.com.br/v1/eu \
-H "Authorization: Bearer $CHAVE"JavaScript
const r = await fetch('https://api.capflux.com.br/v1/eu', {
headers: { Authorization: `Bearer ${process.env.CHAVE}` },
});
console.log(await r.json());Python
import os, requests
r = requests.get('https://api.capflux.com.br/v1/eu', headers={'Authorization': f"Bearer {os.environ['CHAVE']}"})
print(r.json())POST/v1/documentos
Enviar documentos (nota, boleto, anexos)
Cenário 1. Escopo documents:write (todos os planos). Até 20 arquivos e 25 MB por envio: PDF, XML fiscal, imagem, ZIP ou Word. O documento entra na caixa de entrada como qualquer outro; o card aparece quando a leitura termina (consulte GET /v1/documentos/{id}).
| Parâmetro | Onde | Tipo | Descrição |
|---|---|---|---|
Idempotency-Key * | cabeçalho | string | Obrigatório em toda escrita. A mesma chave com o mesmo corpo devolve a mesma resposta (sem duplicar); com outro corpo, 409. |
Corpo (JSON; * = obrigatório)
| Campo | Tipo | Descrição |
|---|---|---|
arquivos * | array | |
assunto | string | ex.: "NF 123 — Fornecedor Fictício Ltda" |
observacao | string |
Respostas
202 | Recebido; a leitura segue em segundo plano. |
400 | Pedido inválido (ex.: sem Idempotency-Key). |
401 | Chave ausente, inválida, revogada ou vencida. |
403 | Escopo insuficiente ou recurso fora do plano. |
409 | Idempotency-Key já usada com outro pedido. |
413 | Envio maior que 25 MB. |
415 | Tipo de arquivo ou de corpo não aceito. |
422 | Campo faltando ou inválido. |
429 | Limite de chamadas por minuto da chave (60 no Essencial, 300 no Profissional). Veja Retry-After. |
curl
curl https://api.capflux.com.br/v1/documentos \
-H "Authorization: Bearer $CHAVE" \
-H "Idempotency-Key: erp-nota-000123" \
-F "arquivos=@nota-000123.pdf" \
-F "arquivos=@nota-000123.xml" \
-F "assunto=NF 123 — Fornecedor Fictício Ltda"JavaScript
import { readFile } from 'node:fs/promises';
const pdf = await readFile('nota-000123.pdf');
const r = await fetch('https://api.capflux.com.br/v1/documentos', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHAVE}`,
'Idempotency-Key': 'erp-nota-000123',
'Content-Type': 'application/json',
},
body: JSON.stringify({
assunto: 'NF 123 — Fornecedor Fictício Ltda',
arquivos: [{ nome: 'nota-000123.pdf', conteudo_base64: pdf.toString('base64') }],
}),
});
console.log(r.status, await r.json()); // 202 { documento_id, situacao: 'recebida', ... }Python
import os, requests
with open('nota-000123.pdf', 'rb') as pdf:
r = requests.post(
'https://api.capflux.com.br/v1/documentos',
headers={'Authorization': f"Bearer {os.environ['CHAVE']}", 'Idempotency-Key': 'erp-nota-000123'},
files=[('arquivos', ('nota-000123.pdf', pdf, 'application/pdf'))],
data={'assunto': 'NF 123 — Fornecedor Fictício Ltda'},
)
print(r.status_code, r.json())GET/v1/documentos/{id}
Situação de um documento enviado
| Parâmetro | Onde | Tipo | Descrição |
|---|---|---|---|
id * | no endereço | string |
Respostas
200 | Situação atual. |
401 | Chave ausente, inválida, revogada ou vencida. |
403 | Escopo insuficiente ou recurso fora do plano. |
404 | Não existe nesta empresa. |
curl
curl https://api.capflux.com.br/v1/documentos/$DOCUMENTO_ID \
-H "Authorization: Bearer $CHAVE"JavaScript
const r = await fetch(`https://api.capflux.com.br/v1/documentos/${documentoId}`, {
headers: { Authorization: `Bearer ${process.env.CHAVE}` },
});
const { situacao, card_id } = await r.json(); // 'virou_card' quando a leitura terminaPython
r = requests.get(f'https://api.capflux.com.br/v1/documentos/{documento_id}', headers={'Authorization': f"Bearer {os.environ['CHAVE']}"})
print(r.json()['situacao'], r.json()['card_id'])GET/v1/cards
Notas aprovadas para lançar · consultar cards
Escopo cards:read (Profissional). Duas leituras no mesmo endereço. Cenário 7, com pronto_para_lancar=true: os cards cuja etapa atual tem passagem de lançamento para "lançado" no fluxo da empresa — a fila pronta para o ERP. Adiantamento não entra: o encerramento depende de prestação de contas/compensação e é feito na tela. Cenário 8, sem pronto_para_lancar: consulta geral para BI (Power BI, Looker), com filtros de etapa, situação, período de criação e atualizado_desde (carga incremental). Cada item traz também atualizado_em e tempos: tempo corrido em segundos em cada etapa e no total, calculado pelo Capflux; o relógio para quando o card entra numa etapa final (lançado ou descartado). Paginação por cursor (ordem de criação): repita a chamada com o proximo_cursor da resposta até ele vir nulo. A fila também pode chegar por webhook.
| Parâmetro | Onde | Tipo | Descrição |
|---|---|---|---|
pronto_para_lancar | na consulta | boolean | true = só a fila pronta para lançar (cenário 7; não combina com os filtros abaixo). |
etapa | na consulta | string | Chaves de etapa separadas por vírgula (ex.: cap,triagem). Etapa que não existe = 422 etapa_desconhecida. |
situacao | na consulta | string: em_andamento, lancado, descartado | |
criado_de | na consulta | string | Criado a partir deste dia (horário de Brasília). |
criado_ate | na consulta | string | Criado até este dia, inclusive. |
atualizado_desde | na consulta | string | Só cards que mudaram desde este momento (ISO 8601 com fuso). Guarde o horário da última carga e repita. |
limite | na consulta | integer | Itens por página (1 a 200; padrão 50). |
cursor | na consulta | string | O proximo_cursor da página anterior. |
Respostas
200 | Uma página (da fila ou da consulta). Na consulta, cada item tem também atualizado_em e tempos. |
401 | Chave ausente, inválida, revogada ou vencida. |
403 | Escopo insuficiente ou recurso fora do plano. |
422 | Filtro, limite ou cursor inválido; etapa desconhecida. |
429 | Limite de chamadas por minuto da chave (60 no Essencial, 300 no Profissional). Veja Retry-After. |
curl
curl "https://api.capflux.com.br/v1/cards?pronto_para_lancar=true&limite=50" \
-H "Authorization: Bearer $CHAVE"
# Próxima página: acrescente &cursor=<proximo_cursor>
# Consulta para BI (cenário 8): o que mudou desde a última carga, com os tempos
curl "https://api.capflux.com.br/v1/cards?atualizado_desde=2026-11-10T08:00:00-03:00&limite=200" \
-H "Authorization: Bearer $CHAVE"JavaScript
// Puxa a fila inteira, página por página.
let cursor = null;
do {
const q = new URLSearchParams({ pronto_para_lancar: 'true', limite: '50', ...(cursor ? { cursor } : {}) });
const r = await fetch(`https://api.capflux.com.br/v1/cards?${q}`, { headers: { Authorization: `Bearer ${process.env.CHAVE}` } });
const page = await r.json();
for (const card of page.itens) console.log(card.codigo, card.fornecedor.nome, card.valores.liquido);
cursor = page.proximo_cursor;
} while (cursor);
// Consulta para BI (cenário 8): sem pronto_para_lancar, com filtros e tempos.
const q = new URLSearchParams({ situacao: 'lancado', criado_de: '2026-11-01', criado_ate: '2026-11-30', limite: '200' });
const bi = await (await fetch(`https://api.capflux.com.br/v1/cards?${q}`, { headers: { Authorization: `Bearer ${process.env.CHAVE}` } })).json();
for (const c of bi.itens) console.log(c.codigo, c.tempos.total_segundos / 86400, 'dias');Python
import os, requests
h = {'Authorization': f"Bearer {os.environ['CHAVE']}"}
params = {'pronto_para_lancar': 'true', 'limite': 50}
while True:
page = requests.get('https://api.capflux.com.br/v1/cards', headers=h, params=params).json()
for card in page['itens']:
print(card['codigo'], card['fornecedor']['nome'], card['valores']['liquido'])
if not page['proximo_cursor']:
break
params['cursor'] = page['proximo_cursor']
# Consulta para BI (cenário 8): o que mudou desde a última carga, com os tempos
bi = requests.get('https://api.capflux.com.br/v1/cards', headers=h, params={'atualizado_desde': '2026-11-10T08:00:00-03:00', 'limite': 200}).json()
for card in bi['itens']:
for etapa in card['tempos']['por_etapa']:
print(card['codigo'], etapa['chave'], etapa['segundos'])POST/v1/pedidos-pagamento
Criar pedido de pagamento sem nota
Cenário 6. Escopo requests:write (Profissional). Reembolso, adiantamento ou despesa de outro sistema viram card na Triagem, como o lançamento manual; as regras de caminho da empresa decidem dali (o tipo é a condição "tipo de documento"), e a resposta já traz a etapa decidida. Sem leitura por IA: os dados são os enviados. A descrição vira a primeira observação do card; o Histórico mostra "API · <nome da chave>". Mesmo número + tipo + favorecido = 409 pedido_duplicado com o card_id (além da Idempotency-Key). Dado bancário do favorecido não entra por aqui: vem do cadastro do fornecedor (PUT /v1/fornecedores, com aprovação na tela). Corpo em JSON (anexos em base64) ou multipart/form-data (campos soltos: tipo, favorecido_nome, favorecido_cnpj_cpf, valor, vencimento, descricao, numero, filial_cnpj, competencia; arquivos em "anexos").
| Parâmetro | Onde | Tipo | Descrição |
|---|---|---|---|
Idempotency-Key * | cabeçalho | string | Obrigatório em toda escrita. A mesma chave com o mesmo corpo devolve a mesma resposta (sem duplicar); com outro corpo, 409. |
Corpo (JSON; * = obrigatório)
| Campo | Tipo | Descrição |
|---|---|---|
tipo * | string: reembolso, adiantamento, despesa | |
favorecido * | object | |
valor * | number | ex.: 150.4 |
vencimento | string | |
descricao * | string | ex.: "Táxi para visita ao cliente" |
numero | string | Número do pedido no sistema de origem. |
filial_cnpj | string | CNPJ da filial que paga (precisa existir na empresa). |
competencia | string | ex.: "2026-11" |
anexos | array | Recibo, comprovante ou autorização: PDF ou imagem, até 10 MB cada. |
Respostas
201 | Card criado (com a etapa já decidida pelas regras). |
401 | Chave ausente, inválida, revogada ou vencida. |
403 | Escopo insuficiente ou recurso fora do plano. |
409 | pedido_duplicado (com card_id) ou Idempotency-Key reaproveitada com outro corpo. |
413 | Anexo acima de 10 MB. |
415 | Anexo que não é PDF nem imagem. |
422 | Campo faltando ou inválido; filial_desconhecida. |
429 | Limite de chamadas por minuto da chave (60 no Essencial, 300 no Profissional). Veja Retry-After. |
curl
curl -X POST https://api.capflux.com.br/v1/pedidos-pagamento \
-H "Authorization: Bearer $CHAVE" \
-H "Idempotency-Key: despesas-RB-2026-0042" \
-H "Content-Type: application/json" \
-d '{
"tipo": "reembolso",
"favorecido": { "nome": "Pessoa Fictícia", "cnpj_cpf": "12345678909" },
"valor": 150.40,
"vencimento": "2026-11-30",
"descricao": "Táxi para visita ao cliente fictício",
"numero": "RB-2026-0042"
}'JavaScript
const r = await fetch('https://api.capflux.com.br/v1/pedidos-pagamento', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHAVE}`,
'Idempotency-Key': 'despesas-RB-2026-0042',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tipo: 'reembolso',
favorecido: { nome: 'Pessoa Fictícia', cnpj_cpf: '12345678909' },
valor: 150.4,
descricao: 'Táxi para visita ao cliente fictício',
numero: 'RB-2026-0042',
anexos: [{ nome: 'recibo.pdf', conteudo_base64: reciboBase64 }],
}),
});
const card = await r.json(); // 201: card.etapa diz para onde as regras mandaramPython
import os, requests
with open('recibo.pdf', 'rb') as f:
r = requests.post(
'https://api.capflux.com.br/v1/pedidos-pagamento',
headers={'Authorization': f"Bearer {os.environ['CHAVE']}", 'Idempotency-Key': 'despesas-RB-2026-0042'},
data={'tipo': 'reembolso', 'favorecido_nome': 'Pessoa Fictícia', 'favorecido_cnpj_cpf': '12345678909',
'valor': '150.40', 'descricao': 'Táxi para visita ao cliente fictício', 'numero': 'RB-2026-0042'},
files=[('anexos', ('recibo.pdf', f, 'application/pdf'))],
)
print(r.status_code, r.json()['etapa'])PUT/v1/fornecedores/{cnpj_cpf}
Sincronizar um fornecedor
Cenário 4. Escopo suppliers:write (Profissional). Cria ou atualiza o fornecedor pelo CNPJ/CPF do endereço (com ou sem pontuação). O cadastro (nome, nome_erp, situacao e, por filial, codigo_erp, prazo_pagamento_dias, email_cobranca) entra direto; o que não vier não muda. Conta bancária e Pix NUNCA entram direto: cada item de dados_pagamento vira alteração pendente, que alguém com permissão de alterar dado bancário aprova ou recusa na tela de Fornecedores, sempre com motivo. Até a aprovação, vale o cadastro anterior; os administradores recebem um aviso. Reenviar o mesmo dado não abre outra pendência; dado diferente substitui a pendência anterior. Depois de aprovada, a troca liga o alerta de segurança "dados bancários alterados há pouco" nos cards do fornecedor por 30 dias: o lançamento pela API responde 422 requer_confirmacao_na_tela até uma pessoa conferir. A resposta traz só o dado mascarado (últimos dígitos). Tudo ou nada: com um item inválido, nada é gravado.
| Parâmetro | Onde | Tipo | Descrição |
|---|---|---|---|
cnpj_cpf * | no endereço | string | |
Idempotency-Key * | cabeçalho | string | Obrigatório em toda escrita. A mesma chave com o mesmo corpo devolve a mesma resposta (sem duplicar); com outro corpo, 409. |
Corpo (JSON; * = obrigatório)
| Campo | Tipo | Descrição |
|---|---|---|
nome | string | Razão social. Obrigatório para fornecedor novo. |
nome_erp | string | |
situacao | string: ativo, inativo | |
empresas | array | Dados por filial (filial_cnpj nulo = todas as empresas do grupo). |
dados_pagamento | array | Fica pendente de aprovação na tela. |
motivo | string | Mostrado a quem aprova (ex.: "conta nova informada pelo fornecedor"). |
Respostas
200 | Atualizado. |
201 | Criado. |
401 | Chave ausente, inválida, revogada ou vencida. |
403 | Escopo insuficiente ou recurso fora do plano. |
415 | Corpo que não é JSON. |
422 | Campo inválido (com o campo, ex.: dados_pagamento[0]); filial_desconhecida; nome faltando para fornecedor novo. |
429 | Limite de chamadas por minuto da chave (60 no Essencial, 300 no Profissional). Veja Retry-After. |
curl
curl -X PUT https://api.capflux.com.br/v1/fornecedores/11222333000181 \
-H "Authorization: Bearer $CHAVE" \
-H "Idempotency-Key: erp-forn-11222333000181-20261111" \
-H "Content-Type: application/json" \
-d '{
"nome": "Fornecedor Fictício Ltda",
"empresas": [{ "codigo_erp": "F001", "prazo_pagamento_dias": 28 }],
"dados_pagamento": [{ "tipo": "banco", "banco": "341", "agencia": "1234", "conta": "12345-6", "tipo_conta": "corrente" }],
"motivo": "Conta nova informada pelo fornecedor"
}'
# dados_pagamento volta com situacao "pendente_aprovacao": vale depois que alguém aprovar na tela.JavaScript
const r = await fetch('https://api.capflux.com.br/v1/fornecedores/11222333000181', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CHAVE}`,
'Idempotency-Key': 'erp-forn-11222333000181-20261111',
'Content-Type': 'application/json',
},
body: JSON.stringify({
nome: 'Fornecedor Fictício Ltda',
empresas: [{ codigo_erp: 'F001', prazo_pagamento_dias: 28 }],
dados_pagamento: [{ tipo: 'pix', tipo_chave: 'email', chave: 'financeiro@fornecedor.exemplo' }],
}),
});
const { fornecedor, dados_pagamento } = await r.json(); // dado bancário só mascaradoPython
import os, requests
r = requests.put(
'https://api.capflux.com.br/v1/fornecedores/11222333000181',
headers={'Authorization': f"Bearer {os.environ['CHAVE']}", 'Idempotency-Key': 'erp-forn-11222333000181-20261111'},
json={'nome': 'Fornecedor Fictício Ltda', 'situacao': 'ativo', 'empresas': [{'codigo_erp': 'F001', 'prazo_pagamento_dias': 28}]},
)
print(r.status_code, r.json()['fornecedor']['id'])GET/v1/cards/{id}
Um card
Escopo cards:read (Profissional). Os mesmos dados de um item da fila, inclusive a versao para enviar nas escritas.
| Parâmetro | Onde | Tipo | Descrição |
|---|---|---|---|
id * | no endereço | string |
Respostas
200 | O card. |
401 | Chave ausente, inválida, revogada ou vencida. |
403 | Escopo insuficiente ou recurso fora do plano. |
404 | Não existe nesta empresa. |
curl
curl https://api.capflux.com.br/v1/cards/$CARD_ID \
-H "Authorization: Bearer $CHAVE"JavaScript
const r = await fetch(`https://api.capflux.com.br/v1/cards/${cardId}`, { headers: { Authorization: `Bearer ${process.env.CHAVE}` } });
const card = await r.json(); // card.versao vai nas escritasPython
card = requests.get(f'https://api.capflux.com.br/v1/cards/{card_id}', headers={'Authorization': f"Bearer {os.environ['CHAVE']}"}).json()GET/v1/arquivos/{id}
Baixar um arquivo do card
Escopo cards:read (Profissional). O arquivo_id vem na lista "arquivos" do card (nota, XML, boleto, anexos).
| Parâmetro | Onde | Tipo | Descrição |
|---|---|---|---|
id * | no endereço | string |
Respostas
200 | O arquivo, com o tipo e o nome no cabeçalho. |
401 | Chave ausente, inválida, revogada ou vencida. |
403 | Escopo insuficiente ou recurso fora do plano. |
404 | Não existe nesta empresa. |
curl
curl -OJ https://api.capflux.com.br/v1/arquivos/$ARQUIVO_ID \
-H "Authorization: Bearer $CHAVE"JavaScript
import { writeFile } from 'node:fs/promises';
const r = await fetch(`https://api.capflux.com.br/v1/arquivos/${arquivoId}`, { headers: { Authorization: `Bearer ${process.env.CHAVE}` } });
await writeFile('nota.pdf', Buffer.from(await r.arrayBuffer()));Python
r = requests.get(f'https://api.capflux.com.br/v1/arquivos/{arquivo_id}', headers={'Authorization': f"Bearer {os.environ['CHAVE']}"})
open('nota.pdf', 'wb').write(r.content)POST/v1/cards/{id}/lancamento
Confirmar o lançamento no ERP
Cenário 2. Escopo erp:write (Profissional). Informe o número e a data do documento no ERP: o card segue para "lançado" pela mesma passagem da tela, com os mesmos campos obrigatórios, e o Histórico mostra "API · <nome da chave>". Adiantamento não é lançado pela API (422 nao_pronto_para_lancar com a etapa): o encerramento depende de prestação de contas e é feito na tela. Alerta comum do pagamento (possível duplicada) pede a justificativa no campo justificativa. Alerta de SEGURANÇA do pagamento (dados bancários do fornecedor alterados há pouco, beneficiário do boleto diferente do fornecedor, boleto suspeito) nunca é liberado pela API: a resposta é 422 requer_confirmacao_na_tela e o card espera uma pessoa conferir na tela; depois disso, reenvie com outra Idempotency-Key.
| Parâmetro | Onde | Tipo | Descrição |
|---|---|---|---|
id * | no endereço | string | |
Idempotency-Key * | cabeçalho | string | Obrigatório em toda escrita. A mesma chave com o mesmo corpo devolve a mesma resposta (sem duplicar); com outro corpo, 409. |
Corpo (JSON; * = obrigatório)
| Campo | Tipo | Descrição |
|---|---|---|
numero_documento * | string | ex.: "5100001234" |
data_lancamento * | string | ex.: "2026-11-10" |
vencimento_erp | string | Vencimento lançado no ERP, quando o fluxo pede. |
justificativa | string | Só para alerta comum do pagamento (possível duplicada). |
versao | integer | Opcional. Se vier e o card tiver mudado, 409 card_mudou. |
Respostas
200 | Lançado. Devolve o card atualizado. |
400 | Pedido inválido (ex.: sem Idempotency-Key). |
401 | Chave ausente, inválida, revogada ou vencida. |
403 | Escopo insuficiente ou recurso fora do plano. |
404 | Card não existe nesta empresa. |
409 | card_mudou (a versao enviada não é a atual) ou Idempotency-Key reutilizada. |
422 | nao_pronto_para_lancar ou ja_lancado (com a etapa atual); campos_obrigatorios (lista em campos: complete na tela); justificativa_obrigatoria; requer_confirmacao_na_tela (alerta de segurança: só uma pessoa libera). |
429 | Limite de chamadas por minuto da chave (60 no Essencial, 300 no Profissional). Veja Retry-After. |
curl
curl https://api.capflux.com.br/v1/cards/$CARD_ID/lancamento \
-H "Authorization: Bearer $CHAVE" \
-H "Idempotency-Key: lancamento-5100001234" \
-H "Content-Type: application/json" \
-d '{"numero_documento": "5100001234", "data_lancamento": "2026-11-10", "vencimento_erp": "2026-11-30"}'JavaScript
const r = await fetch(`https://api.capflux.com.br/v1/cards/${cardId}/lancamento`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHAVE}`,
'Idempotency-Key': 'lancamento-5100001234',
'Content-Type': 'application/json',
},
body: JSON.stringify({ numero_documento: '5100001234', data_lancamento: '2026-11-10', vencimento_erp: '2026-11-30' }),
});
if (r.status === 422) {
const { erro } = await r.json();
// requer_confirmacao_na_tela: alerta de segurança do pagamento; uma pessoa confere na tela e você reenvia.
console.log(erro.codigo, erro.mensagem, erro.campos ?? erro.alertas);
}Python
r = requests.post(
f'https://api.capflux.com.br/v1/cards/{card_id}/lancamento',
headers={'Authorization': f"Bearer {os.environ['CHAVE']}", 'Idempotency-Key': 'lancamento-5100001234'},
json={'numero_documento': '5100001234', 'data_lancamento': '2026-11-10', 'vencimento_erp': '2026-11-30'},
)
print(r.status_code, r.json())POST/v1/cards/{id}/pagamento
Informar o pagamento
Cenário 3. Escopo payments:write (Profissional). Só para card lançado. Data programada e/ou data paga, valor e comprovante (PDF ou imagem, até 10 MB) opcionais. Cada envio fica registrado (nada se apaga); vale o mais recente. Alimenta o Portal do Fornecedor. Valor diferente do card (líquido; sem líquido, o bruto) é aceito — o ERP manda o que pagou —, mas a resposta traz divergencia (valor_card, valor_pago, diferenca = pago − card), o Histórico registra e o card ganha o selo "Pago com diferença". Um pagamento seguinte com o valor certo tira o selo.
| Parâmetro | Onde | Tipo | Descrição |
|---|---|---|---|
id * | no endereço | string | |
Idempotency-Key * | cabeçalho | string | Obrigatório em toda escrita. A mesma chave com o mesmo corpo devolve a mesma resposta (sem duplicar); com outro corpo, 409. |
Corpo (JSON; * = obrigatório)
| Campo | Tipo | Descrição |
|---|---|---|
data_programada | string | ex.: "2026-11-20" |
data_paga | string | ex.: "2026-11-20" |
valor | number | ex.: 1234.56 |
observacao | string | |
comprovante | Arquivo | |
versao | integer |
Respostas
201 | Registrado. |
400 | Pedido inválido (ex.: sem Idempotency-Key). |
401 | Chave ausente, inválida, revogada ou vencida. |
403 | Escopo insuficiente ou recurso fora do plano. |
404 | Card não existe nesta empresa. |
409 | Idempotency-Key já usada com outro pedido. |
413 | Comprovante maior que 10 MB. |
415 | Comprovante que não é PDF nem imagem. |
422 | card_nao_lancado (com a etapa atual) ou campo faltando/inválido. |
429 | Limite de chamadas por minuto da chave (60 no Essencial, 300 no Profissional). Veja Retry-After. |
curl
curl https://api.capflux.com.br/v1/cards/$CARD_ID/pagamento \
-H "Authorization: Bearer $CHAVE" \
-H "Idempotency-Key: pagamento-5100001234" \
-F "data_paga=2026-11-20" \
-F "valor=1234.56" \
-F "comprovante=@comprovante.pdf"JavaScript
const r = await fetch(`https://api.capflux.com.br/v1/cards/${cardId}/pagamento`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHAVE}`,
'Idempotency-Key': 'pagamento-5100001234',
'Content-Type': 'application/json',
},
body: JSON.stringify({ data_programada: '2026-11-20', valor: 1234.56 }),
});
console.log(r.status, await r.json()); // 201 { pagamento_id, ... }Python
with open('comprovante.pdf', 'rb') as f:
r = requests.post(
f'https://api.capflux.com.br/v1/cards/{card_id}/pagamento',
headers={'Authorization': f"Bearer {os.environ['CHAVE']}", 'Idempotency-Key': 'pagamento-5100001234'},
data={'data_paga': '2026-11-20', 'valor': '1234.56'},
files={'comprovante': ('comprovante.pdf', f, 'application/pdf')},
)
print(r.status_code, r.json())