Baixar MD
GUIA DE INTEGRAÇÃO

Respostas, validação e estados da API

Este guia detalha o comportamento da API pública da Calebe Pay: respostas HTTP, regras de validação, permissões e acompanhamento das cobranças. Ele complementa integration.md e o contrato openapi.json.

Respostas e retentativas

Não deduza o pagamento pelo HTTP: uma repetição idempotente pode retornar HTTP 200 com uma transação failed, unknown ou pending. Verifique sempre data.status, data.livemode, data.simulated e data.environment.

HTTP / código O que aconteceu Ação correta
201 Nova cobrança registrada e resultado inicial recebido Salve ID e consulte estado
200 + Idempotency-Replayed: true A mesma tentativa já existe Use a transação retornada; não houve nova submissão
202 / processing Tentativa reservada e processamento ainda não concluído Aguarde e consulte; não crie outra chave
202 / unknown O provedor pode ter criado a cobrança, mas a resposta é incerta Consulte a tentativa existente; não envie uma nova cobrança
400 invalid_json JSON inválido/nulo, campos duplicados/desconhecidos, valor incompatível ou mais de um objeto Corrija o payload
400 idempotency_key_required Header ausente ou fora de ^[A-Za-z0-9._:-]{1,128}$ Persista e envie uma chave válida
401 unauthorized Chave ausente, revogada ou inválida Corrija a autenticação; não tente em loop
403 insufficient_scope A chave não permite a operação Solicite uma chave com os scopes necessários
403 tenant_suspended A conta, ou uma conta acima dela na hierarquia, está suspensa Fale com a Calebe Pay
403 live_payments_disabled Pagamentos reais ainda não estão liberados para este ambiente Aguarde a liberação de produção pela Calebe Pay; não contorne a trava
403 live_payment_out_of_scope A cobrança está fora da autorização de produção concedida à conta Use exatamente os dados autorizados ou fale com a Calebe Pay; não troque a chave de idempotência
403 live_key_cannot_simulate A simulação foi pedida com uma chave de produção Simule com uma chave de teste (cp_test_); cobrança real só muda pelo provedor de pagamento
403 live_key_required Cadastro de subtenant solicitado com chave de teste Use uma chave de produção com subtenants:write
403 origin_denied Chamada feita de um navegador com origem não autorizada Chame a API a partir do seu servidor
404 not_found ID inexistente ou fora do escopo Confira o ID, a conta e o modo da chave; recursos de outra hierarquia e cobranças do outro modo (teste ou produção) também respondem 404
409 idempotency_conflict Mesma chave, payload diferente Recupere payload original. Nova chave somente para nova tentativa comercial deliberada
409 reconciliation_required Não há identificador externo para consultar o provedor Não recrie a cobrança; acione o suporte com o ID txn_...
409 provider_status_conflict A atualização externa regrediria um estado final O estado local é preservado; acione o suporte se precisar revisar
409 simulation_not_allowed A cobrança de teste já não está pendente, ou (boleto com paid_with: "pix") o Pix de teste do boleto já não está pendente ou passou do prazo Crie outra cobrança de teste para simular de novo; no boleto, simule o pagamento pelo boleto
400 parent_id_not_allowed O cadastro público tentou escolher o pai do subtenant Remova parent_id; o pai é sempre o tenant da chave
413 request_too_large Corpo JSON ultrapassou 1 MiB Reduza o corpo antes de reenviar
422 validation_error Campo inválido Corrija os dados; veja OpenAPI e a mensagem
422 tenant_from_api_key A criação pública informou outro tenant Remova tenant_id; use a chave emitida para a conta alvo
422 provider_not_configured O método solicitado não está habilitado para a conta Fale com a Calebe Pay para habilitar Pix ou boleto
422 provider_not_available O provider informado no cadastro não está ativo e roteado para a árvore Omita provider_id para seleção automática ou corrija o roteamento
422 provider_method_disabled O método foi desabilitado para a conta Fale com a Calebe Pay; não há o que corrigir na requisição
422 subaccount_not_configured O cadastro financeiro da conta ainda não está ativo Fale com a Calebe Pay; a conta não herda o cadastro da conta acima dela
422 subaccount_credentials_missing O cadastro financeiro da conta está sem credencial utilizável no ambiente Fale com a Calebe Pay; não há o que corrigir na requisição
422 provider_pix_sandbox_unsupported Pix solicitado em um sandbox remoto, que não existe para esse método Use o simulador ou a produção autorizada; boleto possui sandbox remoto
422 simulator_disabled O ambiente não aceita cobranças simuladas Confirme com a Calebe Pay qual ambiente a sua chave usa
422 amount_limit_exceeded Valor acima do limite por cobrança da conta Solicite a revisão do limite; não divida a cobrança automaticamente
422 tenant_fee_sync_pending Sincronização de tarifas ainda pendente; sem nova reserva Aguarde e confira novamente; preserve tentativas já registradas
422 tenant_fee_sync_blocked A sincronização de tarifas requer correção; sem nova reserva Solicite revisão à Calebe Pay; não gere outra chave para tentativas já registradas
422 split_* Recebedores ou taxas da divisão automática incompatíveis; sem nova reserva Solicite revisão da configuração à Calebe Pay; preserve pedidos anteriores
409 tenant_hierarchy_invalid Árvore de tarifas inconsistente Solicite revisão da configuração à Calebe Pay
422 fee_exceeds_amount Soma das tarifas vigentes do método maior que o valor da nova cobrança; emissão recusada Fale com a Calebe Pay para revisar a tarifa
429 rate_limit_exceeded Limite por credencial/IP atingido Aguarde no mínimo 60 s, com jitter; preserve chave/payload
502 provider_rejected Rejeição conhecida na criação; registro local failed preservado Consulte GET pelo error.transaction_id e os diagnósticos; a mesma chave/corpo recupera o registro sem reenvio. HTTP 200 no replay não significa sucesso financeiro
502 provider_refresh_failed Consulta ao provedor falhou e nada foi aplicado Estado local preservado; repita a consulta com espera progressiva. No boleto, se a consulta do boleto ou a do Pix que o acompanha aplicou uma mudança, a resposta é 200 com o estado novo e a outra é repetida em segundo plano
503 payment_settings_unavailable O controle de pagamentos em produção está indisponível Emissão e refresh em produção ficam bloqueados; repita mais tarde com a mesma chave
503 rate_limiter_unavailable O controle de acesso está temporariamente indisponível Só ocorre em login, MFA, senha, QR do app, checkout público e site: esses acessos falham de forma fechada. Chamadas autenticadas (chave de API ou sessão) seguem funcionando. Repita mais tarde com a mesma idempotência
503 reconciliation_required A solicitação foi reservada, mas o resultado não pôde ser gravado Preserve a chave e consulte a transação; não reprocesse o pagamento
500 internal_error ou falha de rede Resposta não confirmada Preserve a chave, consulte e repita somente a tentativa original

Endpoints inexistentes e métodos HTTP incorretos podem receber uma resposta padrão do roteador, que não é o envelope JSON de erro da aplicação.

O serviço não garante Retry-After. O SDK o expõe quando presente, mas o integrador deve ter uma espera mínima própria para 429. Um backoff recomendado para consultas é 5, 10, 20 e 30 segundos com jitter, respeitando o rate limit. Não faça retries automáticos que troquem a chave idempotente.

Validação e normalização

Replays Pix de registros anteriores continuam aceitos com o corpo e a chave originais, mesmo sem telefone/endereço; não reenviam ao provedor. Alterar o corpo na mesma chave retorna 409 idempotency_conflict. Os novos requisitos são aplicados a novas emissões antes da reserva/chamada externa. O SDK createPix é estrito; uma repetição legada deliberada usa request de baixo nível com o corpo original salvo, sem preencher dados nem gerar nova chave. O GET local permanece disponível.

Permissões e hierarquia

Cada usuário do painel tem um perfil, e o perfil é uma lista de permissões granulares, como ver transações, criar cobranças, revogar chaves ou cadastrar clientes. A tabela abaixo mostra os perfis do sistema como vêm de fábrica.

As chaves de API não seguem o perfil editado: valem pelos scopes e pelo access_profile da tabela.

Capacidade Administrador da conta (tenant_admin) Desenvolvedor (developer) Leitura (viewer) Chave de API
Ler transações Própria conta e contas abaixo Própria conta e contas abaixo Própria conta e contas abaixo Scope transactions:read; listagem das contas abaixo por opt-in
Criar Pix, boleto, cartão e checkout Própria conta ou conta abaixo permitida Própria conta ou conta abaixo permitida Não Scope de escrita de cada método; somente na conta da chave
Cadastrar subtenant e tentar conversão Emite a chave padrão da própria conta Não Não Chave padrão de produção com subtenants:write; o tenant da chave é o pai
Atualizar estado pelo provedor Própria hierarquia Não Não transactions:read + scope de escrita do método; própria hierarquia
Simular pagamento ou expiração de cobrança de teste Própria hierarquia Não Não Somente chave de teste: transactions:read + scope de escrita do método
Consultar e emitir chaves Própria hierarquia Própria hierarquia Não Não
Revogar chaves Própria hierarquia Não Não Não
Documentação Sim Sim Sim Pública
Monitor de integrações Não Metadados das cobranças da própria hierarquia; sem request/response brutos Não Não
Ler logs e notificações Própria hierarquia Não Própria hierarquia Não

O perfil desenvolvedor sempre pertence a um tenant e não administra usuários, tenants, tarifas, provedores, webhooks ou transferências. Sua sessão também não estorna, cancela ou captura cobranças. Ele mantém o autoatendimento da própria conta, como senha, MFA e sessões conectadas.

Um tenant pode consultar o total de tarifas cobrado dele e dos tenants abaixo. Não recebe valores, componentes ou identidades de tarifas dos níveis superiores. A composição interna e a taxa configurada no provedor são restritas à administração global. As prévias e transações de perfis vinculados a tenant mostram somente o total da operação e o saldo do estabelecimento.

Chaves emitidas por quem não tem a permissão de verificar e simular cobranças, como o perfil desenvolvedor, recebem access_profile: "developer" e ficam restritas à criação e consulta de cobranças. Essa restrição vale também quando usadas diretamente pela API: scopes de escrita não liberam refresh, simulação, cancelamento, estorno ou captura. Chaves standard mantêm as permissões da tabela. O perfil da chave é definido pelo servidor e não pode ser promovido.

O cadastro público de subtenant é uma operação de produção e só aceita chave standard com subtenants:write. A conta autenticada vira o pai; parent_id é rejeitado. O provider_id pode ser omitido para seleção automática. Na conversão, as taxas padrão do provider completam somente os meios de pagamento ausentes em registration.MerchantSplit; omitir o bloco usa todos os padrões cadastrados. Interprete sempre conversion_status: apenas converted confirma a subconta, enquanto creating e unknown exigem preservar a mesma tentativa idempotente.

Uma chave de teste (cp_test_) opera só sobre cobranças de teste, e uma de produção só sobre as de produção, com as mesmas permissões acima. As contas formam uma árvore: uma software house, por exemplo, enxerga os clientes abaixo dela. Se uma conta for suspensa, as credenciais dela e das contas abaixo deixam de funcionar. Consultas a recursos de outra árvore usam 404 para não expor sua existência.

No GET público de uma transação específica, o pai pode consultar um filho sem o parâmetro include_descendants. Esse parâmetro controla a listagem. Com tenant_id na listagem, o tenant indicado passa a ser a raiz do filtro; include_descendants=true inclui a subárvore dele.

Acompanhar e atualizar uma cobrança

A tentativa é registrada como processing antes da chamada ao provedor, e a chave de idempotência é única por conta, inclusive entre chamadas concorrentes. A chamada ao provedor continua por um prazo limitado mesmo se o cliente desconectar.

Se uma tentativa ficar em processing ou unknown, não crie outra. Leia o registro por GET, use /refresh quando houver provider_reference e, se a API responder reconciliation_required, acione o suporte com o ID txn_... e o request_id: a cobrança pode existir no provedor, e uma nova emissão duplicaria o pagamento.

Diagnóstico da criação e da consulta

Transações incluem provider_error_code, provider_error_message e provider_http_status, todos nullable. O código remoto aceita somente string de 1 a 10 dígitos; a mensagem é uma orientação estática segura da Calebe Pay, de até 400 caracteres; HTTP remoto aceita 100 a 599. Textos brutos do provedor, tokens, QR Code e dados pessoais nunca são gravados nesses campos. Registros anteriores a esse recurso têm valores nulos.

Uma recusa confirmada na criação retorna 502 provider_rejected e error.transaction_id, mesmo quando o provedor responde HTTP 200 e o status da cobrança indica recusa. Resultado incerto permanece 202 com data.status: "unknown"; os diagnósticos não transformam timeout em certeza de falha. Replay de failed/unknown retorna 200 com o registro existente; apenas processing continua 202 no replay. Nunca há reenvio ao provedor nesse replay.

Os erros de pagamento podem incluir transaction_id e os três diagnósticos diretamente no objeto error, além de code, message e request_id. Validações anteriores à reserva não possuem ID local de transação. request_id continua exclusivo da requisição/auditoria, não do DTO de transação. Se uma proteção local impedir o envio depois da reserva, a mensagem identifica bloqueio local e o HTTP remoto permanece nulo.

Uma falha da consulta ao provedor no refresh retorna os diagnósticos daquela consulta em error, com o ID local, mas preserva o estado e o diagnóstico de criação já salvos. Não confunda a recusa de uma consulta atual com o motivo que originou uma cobrança anterior. GET local nunca faz chamada externa e é o primeiro passo para ler o registro existente.

Se os detalhes da recusa antiga não foram capturados, o diagnóstico permanece nulo. Não há como reconstruí-lo a partir do valor, do horário ou do status genérico failed. Um novo POST financeiro cria outra tentativa e não recupera o erro histórico; não use uma nova chave apenas para investigar.

JSON de criação e corpo preparado para envio

GET /v1/transactions/{id}/request consulta dois registros guardados na criação: request, o corpo normalizado com a conta resolvida, e provider_request, o corpo preparado para o provedor. Ambos são persistidos na reserva, antes de uma possível chamada externa. A resposta usa source: "captured" e missing_fields: []; provider_request é null para o simulador. Isso não prova que a transmissão ocorreu, que o provedor aceitou o pedido ou que houve pagamento.

Registros anteriores retornam source: "legacy_partial": somente campos recuperáveis, como valor, referência e pagador conhecido, sem reconstruir o payload remoto ou supor opções antigas. missing_fields descreve as lacunas, incluindo expiração Pix ou opções de boleto não armazenadas. Consulte o contrato e os campos exatos. Não crie uma nova cobrança para preencher esse histórico nem use o objeto parcial como payload de retry.

A autorização é a mesma da leitura de transação: scope transactions:read para chave e isolamento pela hierarquia, com 404 fora do escopo. Tokens, headers e chave de idempotência não fazem parte dos snapshots expostos; dados pessoais do pagador fazem. Os corpos ficam no endpoint de detalhe, não nas listagens gerais. Restrinja acesso, cópias, retenção e exportação desses dados; não registre o JSON completo em logs ou chamados de suporte.

Como o refresh se comporta

O refresh preserva estados finais: paid só avança para refunded; expired só avança para paid, quando o provedor de pagamento confirma um pagamento tardio; failed e refunded não reabrem. Respostas que regrediriam o estado são recusadas. A atualização é condicionada ao estado anterior, para que consultas concorrentes não sobrescrevam uma confirmação mais recente.

O refresh segue o mesmo caminho da conciliação automática: aplica a mesma regra de prazo do Pix e gera o mesmo evento transaction.updated quando o status muda. Em uma cobrança já expired cujo provedor de pagamento ainda não registra pagamento, o refresh responde 200 sem alterar nada.

Na consulta ao provedor, ID externo, valor exato e referência interna txn_... precisam coincidir com o registro local. Uma divergência retorna provider_refresh_failed sem alterar o estado. Um status externo não reconhecido não é tratado como confirmação de cobrança pendente ou paga.

No simulador e no modo de teste, a transação pendente expira sozinha quando o prazo passa; /refresh aplica a mesma regra, sem consultar o provedor de pagamento.

Fora do simulador, um Pix pendente é conferido com o provedor de pagamento poucos minutos depois de expires_at e só então passa a expired — ou a paid, se o pagamento tiver acontecido. Enquanto o provedor de pagamento não responde, a cobrança continua pending.

Em boleto, due_date é uma data de calendário. No simulador, cancel_after_due=true calcula expiração no início do dia posterior ao vencimento mais days_before_cancel, em São Paulo; sem essa opção expires_at é nulo. Fora do simulador, a consulta confirma o status bancário. Boleto real nunca é expirado pelo prazo local. O Pix que acompanha o boleto deixa de valer no fim do dia do vencimento sem mudar o status do boleto; pago esse Pix, a cobrança passa a paid com paid_with: "pix" (veja Pix no boleto). Um boleto em processing indica intenção de pagamento, sem comprovar liquidação. Artefatos de boleto recebidos são validados: URL HTTPS, linha de 47–48 dígitos, código de 44 dígitos e vencimento esperado.

Saúde, limites e rastreabilidade

Limites desta versão

A API pública cobre Pix, boleto e cartão de crédito quando habilitados para a conta, checkouts, assinaturas com Pix Automático, centros de custo, o cadastro de subtenants e a consulta de tudo isso, além de webhooks de saída para as mudanças de status. A lista completa, com o escopo de cada operação, está em Tudo o que dá para fazer pela API. Estornos integrais e alteração de vencimento estão disponíveis nos endpoints abaixo. Não há endpoints públicos de cancelamento ou captura posterior: confirme o estado no seu backend, pelo webhook assinado ou por consulta. O estado de uma cobrança não representa saldo disponível, e nem o modo de teste nem o simulador certificam uma integração financeira real.

Estornos e vencimento

POST /v1/transactions/{id}/refund solicita estorno integral de cartão, Pix ou boleto pago. Envie Idempotency-Key e {} para cartão/Pix. Exige transactions:read e a escrita do método original (pix:write, credit_card:write ou boleto:write). Chaves com access_profile: developer não podem usar essas operações. No painel, a permissão é charges.manage.

Boleto quitado pela linha digitável exige uma conta bancária do próprio pagador:

json
{
  "bank_data": {
    "bank_code": "001",
    "agency": "0001",
    "agency_digit": "",
    "account": "12345",
    "account_digit": "9",
    "account_type": "CC"
  }
}

CC é conta corrente; PP, poupança. Boleto quitado pelo Pix acoplado (paid_with: pix) é estornado pelo Pix e aceita {}; não informe dados bancários nesse caso.

A resposta pode ser 202: refund.status será processing, pending ou unknown, e a cobrança continua paid até uma consulta autenticada confirmar refunded. Acompanhe a leitura local (GET /v1/transactions/{id}) e os eventos transaction.updated, que também informam a situação da operação. Se o banco devolver o pedido para o estado pago depois de processá-lo, a operação fica failed, com refund_not_completed, e uma nova solicitação deliberada pode ser feita.

PATCH /v1/transactions/{id}/boleto altera somente um boleto pending:

json
{ "due_date": "2026-10-20" }

Exige Idempotency-Key, transactions:read e boleto:write. Escolha uma data válida entre hoje e +365 dias em Brasília, diferente da atual. Enquanto boleto_update.status estiver em confirmação, boleto_due_date continua sendo o vencimento confirmado. O PDF e a página do pagador passam a usar a nova data depois da confirmação e da conferência dos artefatos. O Pix existente não é reemitido nem prorrogado; se antecipar o boleto, ele deixa de ser exibido no novo prazo.

As duas operações usam a conta/subconta que emitiu a cobrança. Mesma cobrança, operação, corpo e chave consultam o pedido registrado sem reenviar o comando; corpo diferente na mesma chave retorna 409 idempotency_conflict. Uma operação em confirmação bloqueia outra chave com 409 operation_in_progress. Recusa confirmada retorna 502 provider_operation_rejected; timeout mantém o resultado incerto. Consulte a cobrança antes de decidir por nova tentativa.

No modo de teste, a conclusão é local e gera o mesmo webhook, sem movimentação financeira. Estornar um ciclo não cancela a assinatura; alterar o vencimento de seu boleto não altera o calendário dos próximos ciclos. Abra Assinaturas → Ciclos → Gerenciar cobrança para essas ações.