Guia da Debit API
Guia prático da Debit API — cálculos jurídicos e financeiros do Brasil (Lei 14.905/2024, manual CNJ 2022, EC 103/2019) via REST e MCP.
- Referência interativa (Redoc):
/v1/docs - OpenAPI (JSON):
/v1/openapi.json - Schema de campos de um tipo:
GET /v1/describe/{type} - Resumo para IAs:
/v1/llms.txt
Base URL de produção:
https://a-api.debit.com.br/debitapi(ajuste conforme o host/prefixo do seu ambiente). Nos exemplos abaixo use$BASE.
1. Autenticação
Toda rota (exceto /health e /v1/auth/*) exige Authorization: Bearer <credencial>. Há quatro tipos:
| Tipo | Formato | Como obter | Quando usar |
|---|---|---|---|
| Chave do site | UUID (b62d5a5f-…) |
Painel da debit → menu → API → "Minhas chaves de API" | O jeito mais simples: pega no site e usa |
| Chave de API | dbt_live_… / dbt_test_… |
POST /v1/keys (exige JWT) |
Servidor↔servidor, automações, agentes; permite escopos |
| JWT | eyJ… (~15 min) |
POST /v1/auth/login |
Sessão humana; obrigatório para gerenciar chaves |
| OAuth 2.1 | Bearer via "Login com Debit" | /authorize (PKCE + DCR) |
Conectores MCP (Claude, ChatGPT) |
Chave criada no site (sem escrever código)
Basta logar em debit.com.br, abrir o menu API e criar uma chave. Ela vale em todas as rotas
/v1/* e também no MCP (https://mcp.debit.com.br/mcp), sempre no cabeçalho:
curl -s "$BASE/v1/indices" -H "Authorization: Bearer b62d5a5f-....-............"
As chaves já criadas nesse painel continuam valendo aqui — é a mesma chave, não é preciso gerar outra.
Diferenças em relação à chave dbt_live_:
- escopos: a chave do site recebe todos os escopos (a tela não tem seletor);
- gerenciamento: criar/apagar é no site (apagar lá derruba o acesso na hora), não em
/v1/keys; - não gerencia chaves:
/v1/keyscontinua exigindo JWT (403 HUMAN_ONLY); - guarda: o valor fica em texto puro no banco legado, enquanto a
dbt_guarda só o sha256 — para integrações críticas prefira adbt_.
Em GET /v1/keys (com JWT) as chaves do site aparecem em frontendKeys, com o prefixo apenas.
Chave inexistente, apagada no site ou fora da liberação de acesso → 401 INVALID_API_KEY.
Quem opera o servidor tem três chaves de configuração (.env) para essa via: LEGACY_KEYS_ENABLED
(desliga), LEGACY_KEYS_REQUIRE_PLAN (só contas com plano, regra herdada do painel) e LEGACY_KEYS_SCOPES
(restringe os escopos concedidos).
Login (JWT)
curl -X POST "$BASE/v1/auth/login" \
-H 'Content-Type: application/json' \
-d '{"identifier":"meu_login","senha":"minha_senha"}'
# → { "user": {...}, "accessToken": "eyJ...", "refreshToken": "..." }
Criar uma chave de API (usando o JWT)
curl -X POST "$BASE/v1/keys" \
-H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' \
-d '{"name":"Integração","scopes":["index:read","calc:read","calc:write","calc:export"]}'
# → { "id": 7, "key": "dbt_live_...", "warning": "Guarde a chave agora — não será exibida de novo." }
Escopos
index:read · calc:read · calc:write · calc:export · extract:run · account:read.
Sem o escopo necessário → 403. Sem credencial válida → 401.
dbt_live_ e dbt_test_: não existe sandbox
POST /v1/keys aceita "env": "test" e devolve uma chave com prefixo dbt_test_. Isso é só um rótulo, para você separar credenciais nos seus próprios ambientes. Não há ambiente de testes: uma chave dbt_test_ fala com a mesma base de produção, cria cálculos reais na sua conta e eles aparecem no site como qualquer outro. As duas chaves são idênticas em permissão e efeito.
Para experimentar sem sujar a conta, use POST /v1/correct sem save (não persiste nada) e apague os cálculos de teste com DELETE /v1/calc/{type}/{id}.
2. Conceitos
- Cálculo salvo: criar/rodar grava na conta real do usuário — o cálculo aparece no dashboard do site.
calcId: é a única referência de que você precisa. Sua credencial identifica a conta, e o gateway confere que o cálculo é dela antes de qualquer operação — cálculo de outra conta responde403.hash: token do link público do cálculo (calculadoras.debit.com.br/{calculadora}?id=…&hash=…), o que permite abrir um cálculo sem estar logado. Vem noPOST /v1/calce no corpo doGET /v1/calc/{type}/{id}. Não é necessário na API —PATCH,runeexportaceitam se você mandar, mas não exigem. Se você tinha guardado um, ele continua valendo.- Tipos de cálculo: 8 tipos (tabela na seção 5). Cada um tem campos próprios — descubra-os em
GET /v1/describe/{type}. - Índice ≠ tabela: um índice é uma série (IPCA-E, INPC, Selic) — liste em
GET /v1/indices. Uma tabela judicial diz qual índice corrige cada mês e quais juros incidem (CJF, TJ/SP…) — liste emGET /v1/tables. São rotas e espaços de id separados; ver a seção 6.
3. Fluxo de um cálculo salvo
POST /v1/calc → cria → { calcId, hash }
PATCH /v1/calc/{type}/{id} → preenche { "fields": { … } }
POST /v1/calc/{type}/{id}/run → roda → totais + memória
GET /v1/calc/{type}/{id}/export → PDF/HTML/Excel
DELETE /v1/calc/{type}/{id} → manda para a lixeira
Os campos vão dentro de
fields.{"dia_atualiza": "25/08/2026"}na raiz do corpo não grava nada — e responde400 NO_FIELDSdizendo exatamente isso. O correto é{"fields": {"dia_atualiza": "25/08/2026"}}. Mande todos os campos numPATCHsó: além de mais rápido, é o que mantém o consumo de limite em 1 (ver seção 8).
Excluir um cálculo
DELETE /v1/calc/{type}/{id} (escopo calc:write) manda o cálculo para a lixeira — o mesmo soft-delete do site. Ele some de GET /v1/calc e continua recuperável pelo site; a API não tem desfazer.
Retomar um cálculo que já existe
Não precisa ter criado o cálculo por aqui, nem ter guardado nada: GET /v1/calc lista o que está na conta — inclusive o que foi feito no site — e o calcId de lá entra direto nas rotas acima.
# o que existe na conta (mesma lista do dashboard)
curl -s "$BASE/v1/calc?limit=20" -H "Authorization: Bearer $KEY"
# → { "calculations": [ { "calcId": 91234, "type": "pensaoAlimenticia",
# "name": "Cliente X", "createdAt": …, "updatedAt": … } ] }
# e daí em diante é só o calcId
curl -s -X POST "$BASE/v1/calc/pensaoAlimenticia/91234/run" \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{}'
Filtre por tipo com ?type=, pagine com ?limit= e ?offset=.
Cálculos de geração anterior (só leitura)
Contas antigas têm atualizacaoMonetaria criados em versões anteriores da
calculadora. Quando elas foram migradas, o que ficou guardado foi o
demonstrativo em PDF, não os dados de entrada — então esses cálculos
aparecem na conta e na listagem, mas não são recalculáveis. No site eles
abrem apenas para consulta.
Na API:
| operação | resposta |
|---|---|
GET …/export?format=pdf |
o PDF arquivado — é o que existe do cálculo |
run, PATCH, GET /v1/calc/{type}/{id} |
409 LEGACY_CALC_READ_ONLY |
export em html/excel |
400 EXPORT_UNAVAILABLE |
Quem exporta um acervo inteiro precisa tratar o 409 como "baixe o PDF", não
como falha: numa conta real eles foram 731 de 4.186 (18%).
Exemplo completo (atualização monetária) — curl
# 1) criar
CREATE=$(curl -s -X POST "$BASE/v1/calc" -H "Authorization: Bearer $KEY" \
-H 'Content-Type: application/json' -d '{"type":"atualizacaoMonetaria","name":"Correção IPCA-E"}')
ID=$(echo "$CREATE" | jq -r .calcId)
# 2) preencher (campos do GET /v1/describe/atualizacaoMonetaria)
curl -s -X PATCH "$BASE/v1/calc/atualizacaoMonetaria/$ID" -H "Authorization: Bearer $KEY" \
-H 'Content-Type: application/json' -d '{
"fields":{
"indexador":45,
"dia_atualiza":"01/06/2026",
"lista":[{"dia":"01/03/2019","valor":10000,"desc":"Principal"}],
"calc_jurosm":true, "juros_moratorios.percentual":"1"
}}'
# 3) rodar
curl -s -X POST "$BASE/v1/calc/atualizacaoMonetaria/$ID/run" -H "Authorization: Bearer $KEY" \
-H 'Content-Type: application/json' -d '{}'
# 4) exportar PDF
curl -s "$BASE/v1/calc/atualizacaoMonetaria/$ID/export?format=pdf" \
-H "Authorization: Bearer $KEY" -o calculo.pdf
O mesmo em JavaScript (fetch)
const h = { Authorization: `Bearer ${KEY}`, 'Content-Type': 'application/json' };
const base = process.env.BASE;
const { calcId } = await (await fetch(`${base}/v1/calc`, {
method: 'POST', headers: h, body: JSON.stringify({ type: 'atualizacaoMonetaria', name: 'Correção' }),
})).json();
await fetch(`${base}/v1/calc/atualizacaoMonetaria/${calcId}`, {
method: 'PATCH', headers: h, body: JSON.stringify({
fields: {
indexador: 45, dia_atualiza: '01/06/2026',
lista: [{ dia: '01/03/2019', valor: 10000 }],
calc_jurosm: true, 'juros_moratorios.percentual': '1',
},
}),
});
const resultado = await (await fetch(`${base}/v1/calc/atualizacaoMonetaria/${calcId}/run`, {
method: 'POST', headers: h, body: JSON.stringify({}),
})).json();
Atalho: correção monetária em uma chamada
Para atualizacaoMonetaria, o POST /v1/correct faz criar→preencher→rodar de uma vez:
curl -s -X POST "$BASE/v1/correct" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{
"index":"ipca_e", "updateTo":"01/06/2026",
"items":[{"date":"01/03/2019","amount":10000,"description":"Principal"}],
"juros":{"percentual":"1","from":"citacao"}, "save":false
}'
Para corrigir por uma tabela judicial em vez de por um índice, troque index por table (o id de GET /v1/tables). Os juros e os períodos de SELIC da tabela entram sozinhos:
curl -s -X POST "$BASE/v1/correct" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{
"table":23176, "updateTo":"01/08/2026",
"items":[{"date":"01/03/2019","amount":10000,"description":"Principal"}]
}'
Mandar index e table juntos é 400 CONFLICTING_FIELDS — os dois gravam o mesmo campo do motor.
SELIC: início, fim e base
A SELIC pode entrar por dois caminhos, e eles nunca somam:
- EC 113 —
"selic": trueliga a SELIC a partir deselic_inicio, no lugar de correção+juros; - tabela judicial — quando você usa
table(ou o campotabelaJudicial, no cálculo salvo) e a tabela já traz período de SELIC (as do CJF, por exemplo, usam SELIC de 12/2021 a 08/2025), ela é aplicada automaticamente, sem pedir nada. Ligar"selic": truepor cima substitui a da tabela.
Dois campos ajustam a rubrica nos dois casos:
| campo | efeito |
|---|---|
selicUntil |
Data final da SELIC da EC 113 (só vale com "selic": true). Omitido = até a data de atualização. Preenchido, depois dele o índice volta a corrigir e os juros voltam a correr. Não recorta a SELIC de uma tabela judicial — lá o período é o que a tabela declara. |
selicBase |
Base de incidência: a (valor atualizado), am (+multa), aj (+juros moratórios e compensatórios), ajm (+juros+multa). |
selicVersion |
Como as datas da SELIC são lidas: 1 (ou omitido) conta por mês — o dia de selicFrom/selicUntil é ignorado e o mês entra inteiro; 2 conta por dia. |
selicBase omitido em cálculo já existente vale ajm, que é o comportamento histórico — é o que garante que nenhum cálculo antigo mude de valor. Cálculo novo nasce com am.
SELIC por dia (selicVersion: 2)
Com selicVersion: 2, as datas da SELIC valem ao pé da letra e o mês em que ela entra (ou sai)
é contado proporcional aos dias, em vez de inteiro. Uma SELIC a partir de 15/03/2022 faz março
render 17 dos 31 dias — a mesma conta pró-rata que a correção por índice já usa (linear sobre a
taxa do mês, dias reais no divisor; não existe série diária de SELIC, a do Bacen é mensal).
Duas condições, e as duas precisam valer:
selicVersion: 2;- o pró-rata da correção ligado —
calc_perc_prorata: "1", oucalc_tj_prorata: "1"quando o indexador é uma tabela judicial. É o mesmo interruptor da correção, de propósito: SELIC e índice contando por critérios diferentes no mesmo cálculo seria incoerente.
Só a ponta inicial é prorateada. É o que o Cálculo Judicial faz na SELIC, e a paridade entre os dois produtos é verificada por arnês — pedir a mesma coisa nos dois tem de dar o mesmo número.
⚠️ Cálculo salvo antes desta opção não tem o carimbo e continua contando por mês, ao centavo,
mesmo com o pró-rata ligado. Chamada por API é sempre nova: informe selicVersion: 2 para contar
o dia. Cálculo criado pela tela já nasce com ele.
A resposta traz selic no resumo e em cada item sempre que houver SELIC, por qualquer dos dois caminhos.
4. Nomes de campo (importante)
Os campos enviados em fields (PATCH) usam chaves achatadas — as mesmas que o GET /v1/describe/{type} lista. Regras por família de tipo:
- atualizacaoMonetaria / pensaoAlimenticia: chaves pontilhadas como
juros_moratorios.percentualoufixacao.tipo(sem o prefixoinfo.). Arrays especiais:lista,pagamentos. - cartaoPonto:
horariorecebe um objeto estruturado por marcação; demais campos no topo. - calculosJudiciais / tabelasJudiciais / saldoDevedor / tabelasFinanciamento / prevDifNRecebidas: chave = o próprio nome do campo (topo).
Sempre confira a lista oficial em GET /v1/describe/{type} — ela traz campo, tipo, required, descricao e valores (enums).
O que é conferido antes de gravar
O gateway valida o lote antes de tocar no cálculo — se qualquer campo estiver errado, nada é gravado:
- formato de data (
DD/MM/AAAAouMM/AAAA), inclusive datas que não existem (31/02, mês 13,29/02em ano não bissexto); - enums, com a lista de valores aceitos na mensagem;
- números e booleanos —
"muito"num percentual é recusado,"1"e1valem; - itens de array, campo a campo, contra o molde do
describe(array<{dia:DD/MM/AAAA, valor:number, …}>): o erro aponta o índice, comolista[1].dia; - ids de índice/tabela, contra o catálogo (
INDEX_NOT_FOUND,INDEX_NOT_TABLE).
Isso existe porque o motor não recusa entrada malformada: ele calcula e devolve R$ 0,00 com HTTP 200. Um laudo zerado com cara de laudo pronto é pior que um erro.
Índices: slug e id
Todo índice do catálogo tem id; a maioria também tem slug (ipca_e, inpc, selic…), e os dois resolvem em GET /v1/indices/{slug|id}. Quando dois índices compartilham a mesma série de dados, o mais antigo mantém o slug histórico e o outro recebe um nome próprio — hoje selic (id 23) e selic_mais1 (id 31, "Selic + 1% (RFB)"), indice_tj_tabela_uniforme_geral (id 58, TJ/MA) e tjmt (id 69). Nunca há dois índices com o mesmo slug.
Tabelas judiciais: GET /v1/tables
Tabela judicial não é índice, e desde 26/08/2026 tem rota própria. GET /v1/tables devolve id, slug (o urlamigavel do site) e name. Esse id é o calcId real da tabela — o mesmo espaço de id das tabelas que você cria em POST /v1/calc {"type":"tabelasJudiciais"} —, e é ele que vai em indexador de um calculosJudiciais.
Se você integrou antes desta data: as tabelas vinham dentro de
GET /v1/indices, como as entradas semslug, e com o id somado de 1000. Aquele número nunca funcionou emindexador: o motor procurava outra tabela (ou nenhuma) e o cálculo voltava com o valor nominal, coeficiente 1 eresumoTab.indexador: 0— comHTTP 200e sem erro. Hoje esse id é recusado com400 INDEX_LEGACY_IDinformando o número correto, e o campolegacyCatalogIdde/v1/tablespermite reconhecê-lo. Subtraia 1000 do id antigo, ou simplesmente relista em/v1/tables.
Nem todo índice serve a todo tipo de cálculo: o selic_mais1, por exemplo, é usado dentro de uma tabela judicial (vl: [{ m, i: 31 }]) e não é aceito pelo motor de atualização monetária, que responde 502 ENGINE_NO_RESULT.
Baixar a série de um índice
GET /v1/indices/{slug|id}/series (escopo index:read) devolve o histórico mês a mês.
curl -s "$BASE/v1/indices/ipca_e/series?from=2024-01&to=2024-03" -H "Authorization: Bearer $KEY"
{
"index": { "id": 45, "slug": "ipca_e", "name": "IPCA-E (IBGE)", "kind": "index", "type": "perc" },
"basis": { "valueMeaning": "monthly_percent", "factorField": "accumulated",
"formula": "corrigido = valor * accumulated[ate] / accumulated[de]",
"variants": { "accumulatedPositive": "expurga os meses de indice negativo; NAO e o padrao da debit" } },
"sampling": "first_day_of_month",
"from": "2024-01", "to": "2024-03", "count": 3, "truncated": false,
"series": [ { "month": "2024-01", "date": "2024-01-01", "value": 0.31,
"accumulated": 5.79, "accumulatedPositive": 5.98, "published": true } ]
}
factorFieldmudou em 26/08/2026: eraaccumulatedPositive, virouaccumulated. A série declarava uma coluna e oPOST /v1/correctdo mesmo servidor calculava por outra — ele cria umatualizacaoMonetariacom o padrãocalc_perc_indice_neg = "1", que lêaccumulated. As duas só coincidem em índice sem mês negativo, e o IPCA tem 22, o IGP-M tem 69. Quem seguia a fórmula publicada não batia com o/v1/correctnem com o laudo. Os dois campos continuam vindo na série: useaccumulatedPositivesó se você quiser mesmo expurgar os meses negativos.Na SELIC,
factorFielderaaccumulatede contradizia a própria fórmula (que é soma, não razão): agora évalue. A colunaaccumulatedda SELIC é NULL em 359 das 481 linhas e vinha como0— hoje vem comonull.
| param | vale para | o que faz |
|---|---|---|
from / to |
ambos | recorta o período (AAAA-MM) |
format=csv |
ambos | devolve text/csv como anexo, em vez de JSON |
sampling=daily |
índice comum | dólar, euro, Ufesp e Ufir têm série DIÁRIA. O padrão (monthly) devolve só a linha do dia 1º — que é a que o cálculo usa. daily devolve a série real |
asOf |
só tabela judicial | data de referência da correção (AAAA-MM-DD) |
Leia o basis antes de usar os números. Ele diz qual campo é o fator e como aplicá-lo: num índice perc quem corrige é o accumulatedPositive, não o value (que é a variação do mês). Multiplicar value dá resultado errado.
value: null com published: false é mês ainda não publicado, não deflação — a linha continua na série porque o accumulated dela é legítimo.
Tabela judicial: a série é calculada, não guardada
Tabela judicial (as entradas com kind: "judicial_table", id a partir de 1000) não tem série armazenada: o banco guarda quais índices valem em cada faixa, e o coeficiente é calculado na hora. Duas consequências:
asOfnão recorta, recalcula. O coeficiente de um mesmo mês muda conforme a data para a qual você atualiza. SemasOf, a referência é o último mês da tabela.factoreselicAccruedandam juntos. Nos meses de SELIC ofactorvale 1 e a correção inteira está noselicAccrued, que é aditivo:corrigido = valor * factor * (1 + selicAccrued/100). Usar só ofactorerra o cálculo.
curl -s "$BASE/v1/indices/1007/series?asOf=2026-08-01" -H "Authorization: Bearer $KEY"
Vem também segments, os marcos da tabela — qual índice vale em cada faixa, e a descrição dos percentuais fixados por lei ("Fixado em 42,72%").
A série não traz juros. Correção e juros são contas ortogonais; para juros use POST /v1/correct.
No MCP,
debit_get_index_seriesdevolve no máximo 240 meses (uma série cheia passa de 900 pontos e não cabe bem num contexto de agente). Para a série inteira, ou para planilha, use o REST comformat=csv.
5. Tipos de cálculo
| type | Descrição | Campos obrigatórios típicos |
|---|---|---|
atualizacaoMonetaria |
Correção monetária (Lei 14.905/2024) | indexador, dia_atualiza, lista |
calculosJudiciais |
Liquidação de sentença | indexador, dataAtual, valorList |
cartaoPonto |
Horas extras a partir do ponto | jornada, horario |
pensaoAlimenticia |
Débito de pensão + atualização | fixacao.tipo, dia_atualiza, lista |
saldoDevedor |
Revisão de financiamento | valor, juros, juros_periodo, parcelas, dia |
tabelasFinanciamento |
PRICE / SAC / SACRE | valor, juros, parcelas, sistema, carencia |
tabelasJudiciais |
Monta a tabela de correção usada pelos cálculos (não atualiza valores) | vl |
prevDifNRecebidas |
Diferenças previdenciárias | especieBeneficio, dataInicioBeneficio, indexador, valorList |
Os campos completos (todos, com enums e descrições) de cada tipo estão em
GET /v1/describe/{type}. Esta tabela mostra só os mínimos para um cálculo válido.
Fora da API: o cálculo trabalhista (CLT), a RMI previdenciária e a contagem de tempo de contribuição continuam no site, mas não são expostos por esta API nem pelo MCP. Pedi-los devolve
400 INVALID_TYPE.
Exportação por tipo
| Tipo | HTML | DOCX | Excel | O que o demonstrativo traz | |
|---|---|---|---|---|---|
atualizacaoMonetaria |
✔ | ✔ | ✔ | — | parcelas, correção, juros, multa e honorários |
calculosJudiciais |
✔ | ✔ | ✔ | — | parâmetros, critérios, composição da tabela, parcelas, sucumbências, imputação, resumo e o anexo mês a mês |
pensaoAlimenticia |
✔ | ✔ | — | ✔ | competências, pagamentos, imputação e art. 528 |
tabelasJudiciais |
✔ | ✔ | — | — | a série mensal da tabela e as faixas de juros |
cartaoPonto |
✔ | ✔ | — | — | espelho de ponto por mês, marcações, horas e extras por adicional |
saldoDevedor |
✔ | — | — | — | parâmetros do contrato e evolução do saldo mês a mês |
tabelasFinanciamento |
✔ | — | — | — | planilha de amortização com totais e encargos |
prevDifNRecebidas |
✔ | — | — | — | diferenças por competência, critérios de correção e totalização |
Janela do plano gratuito (retroativo de 2 anos)
O run executa o cálculo na conta do usuário, com o plano que ela tem. Conta sem assinatura ativa calcula os últimos 2 anos; lançamento com data anterior entra no total pelo valor nominal — sem correção monetária, juros, multa nem SELIC. É a mesma régua que o site sempre anunciou em /precos, e vale para atualizacaoMonetaria e calculosJudiciais.
Como reconhecer. Em calculosJudiciais o resultado ganha um bloco (ausente quando nada foi bloqueado, e sempre ausente para assinante):
{
"bloqueio_assinatura": {
"aplicado": true,
"anos": 2,
"dia_minimo": "12/09/2024",
"dia_minimo_int": 20240912,
"mensagem": "Correção monetária e juros anteriores a esta data são exclusivos dos assinantes; o valor entrou no total pelo nominal.",
"linhas": [ { "dia": "15/03/2019", "valor": 10000, "desc": "" } ]
}
}
Cada linha atingida traz bloqueada_assinatura: true e mensagem_bloqueio; no demonstrativo (HTML/PDF) a data sai com asterisco e o texto dos critérios explica o que faltou. O anexo mês a mês (anexarTabela) começa na mesma data.
⚠️ Pagamento nunca é bloqueado. Valor negativo é dedução, e derrubá-lo para o nominal aumentaria o débito contra o devedor. Parcela pode ficar sem correção; dedução, não.
A API antiga /api/v2/calculosJudiciais é cobrada pela apikey e não aplica esta janela.
Multa do art. 774, parágrafo único, do CPC/2015
Ato atentatório à dignidade da justiça: até 20% do valor atualizado do débito em execução, revertida em proveito do exequente. Não é automática — o percentual é fixado pelo juiz, e por isso o campo existe mas nasce desligado.
Disponível nos dois tipos, com os nomes de cada um:
| atualização monetária | cálculo judicial | |
|---|---|---|
| liga | calc_multa_774 |
calcularMulta774 |
| configura | multa_774 |
multa774 |
modo: "p" aplica o percentual sobre a base escolhida; modo: "v" lança o valor em reais que a
decisão arbitrou, pelo nominal. A base tem oito componentes (base_valor_atualizado,
base_juros_moratorios, base_juros_compensatorios, base_multa, base_selic, base_custas,
base_sucumbencias, base_honorarios), todos marcados por padrão — o mesmo padrão da multa do
art. 523, o que faz a base ser igual ao subtotal. base_multa523 e base_honorarios523 ficam
desmarcados: é sanção sobre sanção e exige escolha explícita. Só na atualização monetária existe
base_deducoes (padrão ligado), que abate pagamentos da base.
O objeto pode ser parcial — as chaves ausentes vêm do padrão. Percentual acima de 20% é calculado, e o laudo registra a ressalva; a API só recusa zero, negativo e acima de 100%.
Imputação de pagamentos (arts. 352 a 355 do Código Civil)
Um valor negativo na lista de parcelas é um pagamento. Sem nenhuma opção, ele abate principal e juros ao mesmo tempo, proporcionalmente — que é o comportamento de sempre e continua sendo o padrão.
Ligando imputacao.ativa, o pagamento passa a seguir a ordem legal: primeiro os juros vencidos,
só o excedente no capital (art. 354), entre as dívidas líquidas e vencidas (art. 355). A
consequência prática é que o total fica acima do abatimento direto — quitar juros antes reduz
menos o capital, e o capital que sobra continua rendendo juros.
Disponível nos dois tipos, com os mesmos nomes:
| campo | padrão | o que faz |
|---|---|---|
imputacao.ativa |
false |
liga a imputação dos arts. 352-355 |
imputacao.art354 |
true |
juros vencidos antes do capital |
imputacao.ordem |
vencimento |
vencimento (mais antiga) ou onerosidade (art. 355, in fine) |
imputacao.permitir_vincendas |
false |
⚠️ imputar em vincenda é compensação, não imputação |
Na atualização monetária, a metodologia sai do campo que já existia: calc_abater_valores
false faz os juros pararem de correr sobre a parte quitada na data do pagamento; true apura
todos os juros até a data de atualização e só então imputa. Não há chave nova para isso.
O excedente que não encontra parcela vencida não abate nada: sai em
imputacao_credito_nao_imputado (atualização monetária) ou imputacao.credito_nao_imputado
(cálculo judicial), informado à parte. Excedente em parcela vincenda seria compensação, vedada.
Em trecho corrigido pela SELIC não há juros destacados — a SELIC já os embute — e ali o art. 354 fica sem objeto: o pagamento abate o saldo único. O laudo declara isso.
O resultado traz, além dos totais de sempre, quanto foi para juros, quanto para capital, quais parcelas foram quitadas e uma linha por par pagamento × parcela. O laudo (HTML, PDF e DOCX) ganha a seção "Imputação dos pagamentos"; o cálculo judicial ganha as colunas "Imput. em juros" e "Imput. no capital" no demonstrativo.
Consulte, não decore.
GET /v1/describe/{type}traz o campoexportFormatscom os formatos daquele tipo, gerado do mesmo objeto que decide a rota — é a fonte que não tem como divergir. A tabela acima é cortesia.
O PDF é desenhado (pdfkit): é o mesmo documento que o site entrega. Os três tipos sem PDF são os que ainda não têm renderizador — não é limitação da API.
O DOCX é OOXML de verdade (não HTML com a extensão trocada): o Word abre sem
o aviso de conteúdo incompatível, e as tabelas continuam sendo tabelas
editáveis. É o mesmo laudo do HTML e do PDF — mesma redação, mesmos números,
mesma ordem; só muda o meio. Existe em atualizacaoMonetaria e em calculosJudiciais.
Pedir um formato indisponível devolve 400 EXPORT_UNAVAILABLE com a lista do que existe para aquele tipo.
Pelo MCP, debit_export_calculation devolve o HTML inline e o arquivo de
pdf/docx/excel — um bloco resource com o conteúdo em base64, pronto para o
cliente salvar. Não é link: os bytes chegam no mesmo turno, sem segunda ida à
rede e sem precisar da chave. Acima de 6 MB (MCP_EXPORT_BLOB_MAX_BYTES) o
arquivo não é embutido e aí sim volta a URL do REST, com o tamanho medido.
Destaques de valores
- pensaoAlimenticia →
fixacao.tipo:percentual_sm,valor_fixo,percentual_liquido,percentual_bruto,mista. - tabelasFinanciamento →
sistema:PRICE,SAC,SACRE. - calculosJudiciais / prevDifNRecebidas →
indexador: é o id de uma tabela judicial, não de um índice — oiddeGET /v1/tables, ou ocalcIdde uma tabela sua (type: "tabelasJudiciais"). Um id deGET /v1/indicese o id antigo do catálogo (calcId + 1000) são recusados com400: sem tabela o cálculo sairia com o valor nominal. Use-1para mandar a série emtabelaPersonalizada. - atualizacaoMonetaria →
indexadorvstabelaJudicial: aqui são dois campos diferentes.indexadoré o índice econômico (45= IPCA-E);tabelaJudicialé o id deGET /v1/tables. Mandar os dois é400. É o único tipo com essa separação, e ela existe porque os dois espaços de id se sobrepõem — a tabela1do CJF e o índice1(BTN) são o mesmo número com significados diferentes. - cartaoPonto →
horario.mesano: mês absoluto (ano × 12 + mês), inteiro — não"MM/AAAA". Março/2024 =2024×12+3=24291. Cada chamada grava uma marcação (periodo0–5,es=e/s), então uma jornada de 8h-12h/13h-18h são quatro chamadas. juros_periodo/iof_periodo:m(ao mês) oua(ao ano).jurosFaixas(judicial): juros moratórios por FAIXA com data completa —{inicio, fim, tipo, percentual}, o mesmo vocabulário do Debit Atualiza e o formato preferido.tipo:s(simples ao mês, percentual livre — 0 é sem juros, 0.5 é 6% a.a., 1 é 12% a.a.),c(capitalizados mensalmente),taxalegal,poupanca_204_simples,tr(juros equivalentes à TRD/TR, Lei 8.177/91, art. 39, caput: variação mensal da TR, sem capitalização). Sentinelas:inicioem branco na primeira faixa vale "desde a data de cada parcela";fimem branco na última vale "até a data do cálculo" — grave em branco, e não a data literal, senão os juros congelam quandodataAtualmudar. Borda: a faixa seguinte começa no dia seguinte ao fim da anterior; datas iguais são recusadas, porque faixas sobrepostas são somadas e os juros saem em dobro.percentualcom vírgula é recusado (viraria zero em silêncio). Informar este campo liga o modo por dia.jurosCompFaixasé o gêmeo dos compensatórios, e é nele que se põe o termo inicial deles (ojurosDataInicionão os alcança).jurosProprios(judicial): fazjurosFaixasvencer os juros da tabela judicial. Padrão false — as tabelas CJF trazem a metodologia de juros delas, e enquanto isto estiver desligado ojurosFaixasfica gravado mas não entra na conta. ⚠️ O padrão não pode inverter: todo cálculo nasce com uma faixa{s, 0}("sem juros"), então a precedência invertida por padrão faria todo cálculo novo sobre uma tabela CJF render juros zero. Ligado, o laudo declara a substituição — a tabela continua aparecendo como fonte da correção monetária. Não alcança os períodos de índice especial (210/211) nem os de SELIC, onde o juros é parte do índice.jurosProRata(judicial): conta os dias quebrados dos juros. Padrão true. Comfalseos juros passam a ser contados por mês inteiro, os dias que sobram são desprezados e um período de 22 dias pode render zero — e isso não é o motor mensal antigo: costuma dar menos juros que ele (1% a.m. de 15/01/2020 a 01/01/2021: mensal legado 12,00%, por dia com pró-rata 11,57%, por dia sem pró-rata 11,00%). As faixas de poupança ignoram o interruptor.jurosTab[].modo(judicial, LEGADO — prefirajurosFaixas):L=taxa legal,6=0,5% a.m.,12=1% a.m.,P=poupança. OateéintMesAno; comjurosDetalhado: truetambém aceitaDD/MM/AAAA, e aí a faixa fecha no dia e a seguinte começa no dia seguinte.jurosDetalhado(judicial): conta os juros por dia (pró-rata die), pelo mesmo critério do Debit Atualiza — meses inteiros mais os dias restantes, estes divididos por 30. Sem ele (o padrão da API), os juros são contados por mês inteiro e o dia da parcela é ignorado: uma parcela de 15/03 rende o mesmo que uma de 01/03. Quando todas as datas caem no dia 1, os dois modos dão exatamente o mesmo número — é o que garante que um cálculo salvo não muda de resultado. Vale também para os juros compensatórios e para as faixas de juros da tabela judicial.vl[].corte(tabelasJudiciais): troca de índice no meio do mês.{m, i, corte:[{dia, i}]}, ondediaé o primeiro dia do índice novo eicontinua sendo o do primeiro segmento — por isso quem lê só.icontinua funcionando. Ex.:{m:24245, i:45, corte:[{dia:12, i:23}]}= maio/2020 com 11 dias de IPCA-E e 20 de Selic. As séries são mensais (não existe IPCA diário), então o mês partido é pró-rata proporcional aos dias da variação do mês — diga isso no laudo. Duas restrições: percentual fixado (fixo) e índice com juros embutidos (210/211) não podem começar no meio do mês. Nos marcos declarativos, basta pôr o dia node:{"ate":"11/05/2020","i":45}seguido de{"de":"12/05/2020","ate":"HOJE","i":23}.correcaoProRata(judicial): corrige pró-rata die pela data da parcela — 15/03 rende só os dias dela em março, em vez do mês inteiro. Mesma conta do Debit Atualiza. Padrãofalse, inclusive em cálculo novo: contar a correção por dia é escolha de metodologia (o Manual de Cálculos da JF trabalha em meses inteiros), não refinamento aritmético. No atualiza a chave écalc_tj_prorata. É independente dojurosDetalhado— um é o pró-rata da correção, o outro o dos juros.jurosDataInicio(judicial): termo inicial dos juros moratórios (citação, imissão na posse, trânsito em julgado), emDD/MM/AAAA. Nenhuma parcela rende juros antes dessa data. Vale inclusive quando a tabela judicial já define os juros — a tabela manda no tipo, esta data manda em quando começa. Nos meses de índice com juros embutido (SELIC, IPCA+2%, INPC+2%) vale o critério do próprio índice.
6. Extração de documentos (IA)
Tamanho. O teto é de 25 MB por arquivo, aplicado sobre o arquivo já decodificado. Em
fileBase64o corpo cresce ~33%, então o parser aceita até ~34 MB de JSON — mandar o arquivo como multipart (campofile) evita esse acréscimo. Acima de ~20 MB a própria IA costuma recusar por tamanho, e a resposta vem como413 FILE_TOO_LARGEdizendo exatamente isso. Documento ilegível ou fora de formato volta como502 EXTRACT_FAILEDcom o motivo. Corpos muito acima do teto (dezenas de MB) podem ser recusados já pelo proxy, com um413sem o envelope JSON — a semântica é a mesma.
POST /v1/extract (escopo extract:run) lê CNIS, sentença, cartão de ponto ou doc trabalhista:
curl -s -X POST "$BASE/v1/extract" -H "Authorization: Bearer $KEY" \
-F 'docType=cnis' -F '[email protected]'
# ou JSON: { "docType":"cnis", "fileBase64":"...", "filename":"cnis.pdf" }
docType: cnis | sentenca | cartaoPonto | trabalhista. O resultado pode alimentar sc (rmi), valorList, etc.
Retenção (LGPD). O arquivo enviado é apagado do servidor 48 horas depois do upload, junto com os dados que a IA extraiu dele. A resposta desta chamada é a única cópia do resultado — guarde-a, ou aplique-a a um cálculo, na mesma sessão. Não existe rota para rebaixar o documento depois. A exceção é o arquivo fiscal de ponto (AFD/AEJ) importado por
/importarPontoFiscal, que não passa por IA e é guardado por 30 dias porque o passo de aplicação o relê.
7. MCP (agentes de IA)
A raiz do host (
GET /) é pública e serve de índice: abre uma página com o endereço do MCP, a base REST e os links de documentação; para cliente de API (Accept: application/json) devolve o mesmo em JSON.GET /mcpcontinua respondendo 405 — o transporte é POST —, mas explica o que fazer em vez de só recusar.
Endpoint POST /mcp (Streamable HTTP, JSON-RPC 2.0), mesma autenticação. As tools espelham o REST:
debit_list_indices, debit_list_judicial_tables, debit_get_index_series, debit_describe_calculation_type, debit_correct_value, debit_create_calculation, debit_set_calculation_fields, debit_run_calculation, debit_get_calculation, debit_list_my_calculations, debit_delete_calculation, debit_export_calculation, debit_extract_document.
Conectores remotos (Claude/ChatGPT) descobrem o OAuth via /.well-known/oauth-authorization-server e abrem o "Login com Debit".
8. Erros
Formato padrão:
{ "error": { "code": "FORBIDDEN_SCOPE", "message": "Escopo necessário: calc:write", "hint": "…", "docUrl": "…" } }
| Código | HTTP | Quando acontece / o que fazer |
|---|---|---|
BAD_REQUEST |
400 | Falta um campo do corpo (ex.: index, updateTo, items em /v1/correct). |
INVALID_API_KEY · INVALID_CREDENTIALS |
401 | Chave inexistente/revogada, ou login e senha que não conferem. |
NOT_ALLOWED |
401 | Credencial válida, conta fora da liberação (fase de testes). Fale com o suporte. |
FORBIDDEN_SCOPE |
403 | A chave não tem o escopo da operação. Crie outra em POST /v1/keys com o escopo que falta. |
HUMAN_ONLY |
403 | Gerenciar chaves exige login por JWT — uma chave não cria outra chave. |
FORBIDDEN |
403 | O cálculo é de outra conta. |
FORBIDDEN (do motor) |
403 | O motor recusou o acesso ao cálculo. Em geral um hash enviado que não é o daquele cálculo — se estiver mandando hash, tente sem. |
INVALID_TYPE |
400 | Tipo de cálculo que não existe (a mensagem lista os aceitos). |
TYPE_NOT_DESCRIBED |
404 | Não há schema para esse tipo (idem, a hint traz a lista). |
BAD_ID |
400 | calcId não numérico ou ≤ 0. |
CALC_NOT_FOUND |
404 | O cálculo não existe. |
ENGINE_REJECTED |
409 | O motor recusou rodar o cálculo sem dizer o porquê ({sucesso:0}). Antes isso chegava como 200 com corpo vazio de números. |
INDEX_NOT_FOUND |
400/404 | Índice inexistente em /v1/correct ou /v1/indices/{slug}. |
INDEX_NOT_TABLE |
400 | O campo recebeu um índice onde se espera uma tabela judicial (ou o contrário, em atualizacaoMonetaria). Um índice ali não corrige nada — a mensagem sugere tabelas válidas. |
INDEX_LEGACY_ID |
400 | Id de tabela no formato antigo do catálogo (calcId + 1000), de antes de GET /v1/tables existir. A mensagem traz o id correto. |
TABLE_NOT_FOUND |
400/404 | A tabela judicial não existe — nem no catálogo, nem entre as suas. Sem ela o motor devolveria o valor nominal. Liste em GET /v1/tables. |
TABLE_NO_CORRECTION |
422 | O run de um calculosJudiciais cuja tabela não corrigiu nenhum mês (coeficiente 1, sem juros, sem SELIC). Em geral o indexador aponta para uma tabela apagada. Regrave o campo com um id de GET /v1/tables. |
NO_FIELDS |
400 | PATCH sem fields, ou com fields vazio. Os campos vão dentro de fields: {"fields": {"dia_atualiza": "25/08/2026"}}. A resposta lista as chaves que chegaram na raiz do corpo. |
CONFLICTING_FIELDS |
400 | indexador e tabelaJudicial juntos no mesmo atualizacaoMonetaria — os dois gravam o mesmo campo do motor. |
INVALID_FIELD_FORMAT · INVALID_FIELD_VALUE |
400 | Campo com formato ou valor fora do schema — inclusive dentro de arrays: uma data 01/13/2019 em lista[0].dia é recusada apontando o item. A mensagem diz o esperado; o lote inteiro é recusado, sem gravar nada. |
FIELD_REJECTED |
409 | O motor recusou o valor do campo. |
ENGINE_NO_RESULT |
422 | O motor respondeu vazio — em geral um parâmetro que aquele tipo não suporta (um índice do catálogo que não se aplica ali). Antes isso voltava como 200 sem número nenhum. |
ENGINE_ERROR |
422 | O motor falhou ao gravar/rodar/abrir, e a mensagem traz o erro dele. Antes isso virava espera até o timeout; hoje volta na hora. |
LEGACY_CALC_READ_ONLY |
409 | O cálculo é de uma geração anterior da calculadora de atualização (coluna tipo = ATUA/A2). Na migração ficou guardado o demonstrativo em PDF, não os dados de entrada — não há o que rodar nem alterar. Baixe com export?format=pdf. |
LEGACY_PDF_MISSING |
410 | Cálculo de geração anterior cujo PDF arquivado não está no servidor. Não há como reconstruí-lo. |
CALC_DATA_GONE |
410 | O cálculo está cadastrado na conta, mas o arquivo com os dados não existe mais no servidor. Aparece na listagem (a linha da tabela ficou), e não há o que rodar nem exportar. Cálculos antigos podem ter o arquivo expurgado. |
EXPORT_UNAVAILABLE |
400 | Formato indisponível para o tipo (a mensagem lista os disponíveis). |
BAD_DOCTYPE · NO_FILE |
400 | Extração: docType fora da lista, ou arquivo ausente/vazio. |
FILE_TOO_LARGE |
413 | Arquivo acima de 25 MB, corpo acima do que o parser aceita, upload cortado no limite, ou documento recusado pela IA por tamanho — a mensagem diz qual dos casos. |
EXTRACT_FAILED |
502 | A IA recusou o documento (ilegível, formato não suportado). A mensagem traz o motivo que o motor devolveu. |
BAD_JSON |
400 | O corpo não é um JSON válido. |
Por que erro de cálculo é 4xx e não 502. Os hosts públicos ficam atrás do Cloudflare, que substitui o corpo de toda resposta 5xx pela página de erro dele. Um
502com uma mensagem precisa dentro chegava ao cliente comoerror code: 502e um link para a documentação do Cloudflare — a explicação era descartada no caminho. Por isso, desde 26/08/2026, quando o motor responde dizendo que não consegue (ENGINE_ERROR,ENGINE_NO_RESULT,ENGINE_REJECTED,TABLE_NO_CORRECTION) a resposta é 4xx, que atravessa intacta. O502fica para o que ele realmente descreve: motor que não respondeu. |KEY_NOT_FOUND| 404 | Chave inexistente emDELETE /v1/keys/{id}. | |429| 429 | Limite de uso — ver "Limites" abaixo. Pode chegar sem o envelope JSON acima quando quem barra é a borda (nginx), e não o gateway. | |INTERNAL| 500 | Erro não previsto. OrequestIdda resposta identifica a chamada no suporte. |
Todo erro traz
docUrl. Erros de campo (INVALID_FIELD_*) dizem o formato esperado — é o bastante para a chamada seguinte já sair certa, sem tentativa e erro.
Limites (o que causa 429)
Não há cota por plano nem por endpoint. O que existe é um teto interno por usuário, na ponte que executa o cálculo sob a sua conta: 60 operações por minuto e 300 por hora. Ele existe para conter script em laço, não para racionar uso legítimo.
O que consome do teto: POST /v1/calc, PATCH, run, GET /v1/calc/{type}/{id} e export — uma unidade cada. PATCH conta 1 por chamada, não por campo, então preencher um cálculo inteiro num único PATCH com 20 campos custa o mesmo que preencher um campo só. Leitura de catálogo e de série (/v1/indices, /v1/tables, /v1/describe) não consome.
Na prática: agrupe os campos num PATCH só, e guarde o calcId em vez de recriar o cálculo. Ao tomar 429, respeite o retryAfter da resposta (em segundos) — repetir na hora só empurra a janela.