Skip to main content
O que entra aqui. Mudança de contrato: tipo de campo, nome de campo, valor de enum, resposta de erro, endpoint novo ou removido. Melhoria de texto e correção de exemplo na documentação não entram.Como ler. Incompatível altera o que a API já devolvia e exige ação de quem integra. Corrigido, Adicionado e Documentado não exigem nada.
Assinatura nos webhooks e expiração do Pix aplicada de verdade

Adicionado

Webhooks passam a ir assinados. Toda entrega leva agora dois headers novos: X-Cakto-Timestamp (Unix time do envio) e X-Cakto-Signature, no formato v1=<hmac-sha256> — HMAC-SHA256 de {timestamp}.{corpo cru}, com o secret do webhook como chave. Serve para provar a origem sem depender do segredo que vem no corpo, e detecta payload adulterado ou reenviado.Nada muda para quem já valida pelo corpo. O campo secret continua em toda entrega e a validação por comparação segue válida — os headers são adicionais. Ver Validando a origem.

Corrigido

pixExpiresIn passa a valer. O campo era aceito e validado contra o limite do produto, mas não chegava à adquirente: a validade do QR acabava sendo sempre o padrão de quem processou a cobrança. Agora o valor enviado é repassado, e o pix.expirationDate da resposta reflete o que foi pedido.Se você já mandava o campo, a validade do QR muda a partir de agora — passa a ser a que você pediu, em vez do padrão da adquirente (que costumava ser maior). Quem não envia o campo não é afetado: segue valendo o padrão da adquirente, igual a antes.
Juro adicional de parcelamento, e a taxa que o comprador paga

Adicionado

Juro adicional de parcelamento. Três operações novas, escopo payments (a escrita também exige write). É o juro que você cobra do comprador por parcelar, somado por cima do juro-base da Cakto que sai em GET /public_api/fees/ — são dois números diferentes, cobrados por partes diferentes, na mesma parcela.Sobre a configuração:
  • A faixa é de 2x a 12x, sempre com as onze faixas na resposta e sempre na mesma ordem. Não existe juro adicional em 1x. Parcela sem juro configurado vem com interestPercentage: nullnull não é zero.
  • interestPercentage é number em pontos percentuais (1.5 é 1,5%), como toda porcentagem no contrato.
  • active é quem decide se algo é cobrado. Com active: false a tabela continua guardada e nada é somado ao comprador — desligar preserva os percentuais em vez de apagá-los. Sempre cruze os dois campos antes de calcular o valor de uma parcela.
  • O PUT substitui a tabela inteira: parcela que não estiver no corpo fica sem juro, e uma lista vazia zera todas. Mandar o mesmo corpo duas vezes deixa a conta no mesmo estado, então a chamada é segura de repetir — e por isso ela não lê o header X-Idempotency-Key.
  • O PUT muda o que o comprador paga, a partir do próximo pagamento parcelado. Pedidos já pagos não mudam. O checkout que o comprador já tem aberto continua exibindo a tabela antiga até recarregar, mas a cobrança usa a tabela nova — os detalhes estão em Configurar Juro Adicional.
  • Não há teto de negócio no percentual — o quanto cobrar é decisão sua, e a API aceita a mesma faixa que o painel. O limite é técnico (99999999.99, o que cabe no campo) e o percentual aceita no máximo duas casas decimais.
  • Reativar é explícito. active omitido vale true, então um PUT sem active sobre uma tabela desligada volta 409 em vez de religar a cobrança em silêncio. Mande active: true para religar, ou active: false para mexer nos percentuais mantendo desligado. Com a tabela vigente, ou nunca configurada, omitir segue valendo true.
  • 409 tem três motivos, distinguíveis pelo detail: conta sem cadastro de recebimento concluído, recurso não habilitado para a conta, ou a reativação implícita acima. Nenhum dos três se resolve repetindo a chamada.
GET /public_api/fees/ passou a devolver customerFees. Campo novo, aditivo — a lista de taxas que a Cakto cobra do comprador nas vendas da sua conta, somadas ao total que ele paga e que não saem do seu repasse. Ver Taxas e Prazos.
  • Hoje traz uma linha: Taxa de serviço, amount "0.99", todos os métodos (paymentMethod: null), devolvida ao comprador no reembolso (refundable: true). O valor é por pedido, não por parcela, e não varia com o valor da venda.
  • Leia a lista, não assuma os R$ 0,99. Em parte das contas essa taxa é cobrada do produtor em vez do comprador, ou não é cobrada — nesses casos ela não aparece, e customerFees: [] é resposta válida.
  • É lista, e não um campo fixo, justamente para a composição poder mudar sem quebrar quem já integra.
  • Se você monta a tela de preço do comprador, o total dele é o produto mais amount. Se você calcula o seu líquido, customerFees não entra na conta.
Sobre os ganhos:
  • A resposta traz charged e earned lado a lado, e eles não são o mesmo número. charged é o juro que o comprador pagou nos seus pedidos; earned é a fatia que ficou com você depois do rateio por comissão. Num produto com coprodutor a 30%, earned é 70% de charged. Somar o juro dos pedidos e chamar de ganho superestima quem divide receita.
  • Os dois vêm como string decimal ("1000.00"), como todo dinheiro no contrato novo.
  • A janela é obrigatória por consequência: sem startDate/endDate a consulta responde os últimos 30 dias, e o período pedido não pode passar de 92 dias (400 acima disso). Os campos startDate e endDate da resposta ecoam a janela que foi realmente aplicada — confira, principalmente se você não mandou nenhuma das duas.
  • Só entram pedidos pagos, e uma consulta responde sobre uma moeda só (currency, padrão BRL).
  • O total de um período passado pode mudar. Não há registro de reversão: se um pedido daquele período for reembolsado ou sofrer chargeback depois, ele sai do total. Se você armazenar o valor, reconcilie em vez de tratá-lo como fechado.
Contrato de pagamentos, webhooks, produtos e taxas

Incompatível

initiate_checkout saiu do catálogo de webhooks. Ele era assinável e nunca foi entregue — é evento de pixel, disparado no carregamento do checkout, quando ainda não existe pedido nem pagamento. Assinar não dava erro e nada chegava. Não há substituto por webhook hoje.Só afeta quem tentou assinar esse evento; nenhuma entrega existente muda.

Corrigido

Nestes casos a documentação descrevia algo diferente do que a API sempre fez. O comportamento não mudou — a referência é que passou a dizer a verdade.
  • Campo de antifraude com o nome errado. Era publicado em camelCase; o contrato só aceita antifraud_profiling_attempt_reference, em snake_case. Quem copiava o exemplo recebia 400.
  • Obrigatoriedade errada do antifraude. Estava marcado como obrigatório nos cinco métodos de pagamento. Só é exigido em credit_card e threeDs.
  • Objeto pix com nomes errados. A referência dizia expiresAt e qrCodeBase64; o real é expirationDate e qrCode. expirationDate também não é date-time: vem como 2026-04-29 01:30:00+00:00, com espaço.
  • Resposta de criar produto descrevia o serializer errado, mostrando 7 campos onde a API devolve 59.
  • Listagem de checkouts documentava paginação dentro de paginação, envelope que a API nunca devolveu. O correto é um envelope só.

Adicionado

GET /public_api/fees/ — taxas e prazos da sua conta. Endpoint novo. Devolve, por método de pagamento, o percentual e o valor fixo cobrados por venda aprovada e o prazo de recebimento em dias, mais a tabela de juro-base do parcelamento no cartão de 1x a 18x. É a mesma informação da tela Taxas e Prazos do painel. Escopo payments, leitura. Ver Taxas e Prazos.
  • Corpo com dois campos: paymentMethods (lista de paymentMethod, percentage, fixed, releaseDays) e creditCardInstallments (lista de installments, interestPercentage).
  • paymentMethods traz sempre os dez métodos, na mesma ordem: pix, pix_auto, boleto, credit_card, threeDs, picpay, pagaleve, googlepay, applepay, openfinance_nubank. Método sem taxa vigente configurada vem com os três valores em nullnull não é zero.
  • fixed vem como string decimal ("2.49"), e percentage e interestPercentage como number em pontos percentuais (4.99 é 4,99%). Não é inconsistência: é o padrão novo, explicado abaixo.
  • 409 tem um único motivo nesta operação: conta sem cadastro de recebimento concluído. 503 é falha temporária ao consultar as taxas, e pode ser repetida com backoff.

Padrão de valores, daqui pra frente

Nada muda no que já existe. Esta seção descreve a regra que passa a valer para o que for publicado a partir de agora, para você não ser surpreendido pela diferença.
A API não tinha regra sobre o tipo de valor: o mesmo produto sai "197.00" no POST que o cria e 197.0 no GET seguinte. A partir de agora, o que for publicado segue uma regra só:Dinheiro em string porque 0.1 + 0.2 não é 0.3 em ponto flutuante, e dinheiro não tolera esse erro. Percentual não sofre disso e continua number.GET /public_api/fees/ é o primeiro endpoint no padrão: por isso fixed é string e percentage é number no mesmo objeto.Os endpoints que já existem continuam como estão. Migrá-los muda o tipo de campos que integrações em produção já consomem, então será feito com aviso prévio aqui, numa entrada marcada Incompatível, com a lista completa dos campos afetados e o que fazer. Não há data.Se você está escrevendo uma integração nova agora, o mais seguro é converter todo valor monetário para um tipo decimal na entrada, aceitando tanto 2.49 quanto "2.49". Isso já é boa prática para dinheiro e torna a migração um não-evento para você.

Documentado

Campos e comportamentos que sempre existiram e não constavam na referência.
  • Cartão no enum de paymentMethod. credit_card e threeDs sempre foram aceitos, mas a referência listava só pix, pix_auto e boleto. Os objetos card e threeDSecure e o campo installments passaram a constar.
  • Pré-requisito de conta Cakto Banking. Cobrar por pix, pix_auto ou boleto exige conta aberta e ativa; cartão não exige. Ver Pré-requisitos.
  • Corpo entregue nos webhooks, campo a campo, incluindo o fato de data ter duas formas: checkout_abandonment não traz id nem status, e quebra handler que deduplica por data.id. Ver Webhooks.
  • Respostas de erro 400, 403 e 404 em 16 operações que não as declaravam.
  • Campos que a referência omitia: currency em ofertas e produtos, id no cliente do pedido e no order bump, errors no histórico de eventos de webhook, e mais oito campos de produto. Já vinham na resposta; agora estão descritos.