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
Só para assinantes. Desde 28/10/2026 a API — REST e MCP — é exclusiva para contas com plano Debit Atualiza, Trabalhista ou Cálculos (100, 101 ou 110) vigente na própria conta. Sem assinatura, toda rota responde
403 SUBSCRIPTION_REQUIRED, menosGET /v1/mee/v1/keys, que seguem respondendo para você conferir a conta. No MCP a conexão funciona, mas as tools devolvem a mesma mensagem — sódebit_get_accountresponde. Depois de assinar (planos), o acesso volta em até um minuto. Aplicativos parceiros com acordo (o ZenAdv, pelo OAuth) seguem liberados.
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_… |
Não se cria mais (ver abaixo); as já emitidas seguem valendo | Servidor↔servidor, automações, agentes; pode ter escopos restritos |
| JWT | eyJ… (~15 min) |
POST /v1/auth/login |
Sessão humana; obrigatório para listar e revogar chaves |
| OAuth 2.1 | Bearer via "Entrar com Debit" | /authorize (PKCE S256 + DCR) — ver abaixo |
Conectores MCP (Claude, ChatGPT) e aplicativos web (o ZenAdv) |
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.
Este é o único lugar onde se cria chave. Desde 16/10/2026 a API não emite chave — nem pelo REST (
POST /v1/keysresponde410 KEY_CREATION_REMOVED), nem pelo MCP (que nunca teve essa tool). Conectores MCP (Claude, ChatGPT) não precisam de chave: usam o OAuth "Entrar com Debit".
Diferenças em relação à chave dbt_live_ (emitida pela API até 16/10/2026):
- 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.
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": "..." }
Chaves dbt_live_ (não se criam mais)
POST /v1/keys foi desativado em 16/10/2026 e responde 410 KEY_CREATION_REMOVED, com qualquer
credencial. Crie a chave no site (acima). As dbt_live_/dbt_test_ emitidas antes continuam
autenticando com os escopos com que nasceram; com o JWT você ainda as lista (GET /v1/keys) e
revoga (DELETE /v1/keys/{id}).
Escopos
index:read · calc:read · calc:write · calc:export · extract:run · account:read.
Sem o escopo necessário → 403. Sem credencial válida → 401.
OAuth 2.1 — "Entrar com Debit"
Para quem age em nome de uma pessoa sem guardar a senha dela: conectores MCP (Claude, ChatGPT) e aplicativos web (o ZenAdv). Authorization Code com PKCE S256 obrigatório.
- Descoberta: os endpoints saem de
/.well-known/oauth-authorization-server(e o recurso MCP, de/.well-known/oauth-protected-resource/mcp). Não fixe host no código: leia o emissor da configuração e descubra o resto pela metadata. - Cadastro: conectores entram pelo cadastro dinâmico (
POST /register, cliente público). Aplicativo da casa é registrado de antemão, comclient_idfixo eredirect_uriexata. /authorizereaproveita a sessão do app. Se o navegador já está logado no app.debit.com.br, o "Entrar com Debit" não pede senha:- aplicativo da casa (o ZenAdv) volta ao callback na hora, sem tela nenhuma;
- aplicativo de terceiros mostra "Continuar como <nome>", com a lista em português do que será compartilhado e o host para onde a pessoa volta.
- Sem sessão: o botão "Entrar na Debit" leva ao login do app (
/login?next=com o próprio/authorize) — Google, verificação em duas etapas e SSO vêm de lá — e volta. A senha direto na tela continua como alternativa ("Prefere entrar com senha aqui?"). - Só a conta titular autoriza. Usuário da equipe (sub-usuário) recebe "peça ao titular da conta".
- O
statevolta exatamente como foi enviado; recusar ("Cancelar") volta comerror=access_denied. Escopo inexistente é descartado; se não sobra nenhum válido, voltaerror=invalid_scope. Semscopeno pedido, são concedidos todos os escopos acima.
Tokens. POST /token (form). O access token é um JWT de ~15 min com os escopos
concedidos; o refresh token vale 30 dias e rotaciona a cada uso (o antigo deixa de
valer — de duas renovações simultâneas do mesmo token, só uma vence). Regras do refresh:
- renova só no
/tokene só pelo client que o recebeu — outro client →400 invalid_grant; - o escopo nunca passa do consentido: pedir mais →
400 invalid_scope; pedir menos reduz (e o reduzido vira o novo teto); - o refresh do OAuth não vale em
POST /v1/auth/refresh(→401 INVALID_REFRESH), que é só do login humano: um consentimento restrito não vira acesso total à conta; - revogação em
POST /revoke, pelo próprio client (/v1/auth/logouté só do login humano).
Client confidencial. Um client registrado de antemão pode ter segredo: aí o /token e o
/revoke exigem client_secret no corpo (client_secret_post; sem ele, ou errado →
401 invalid_client). PKCE continua obrigatório. Os clientes do cadastro dinâmico seguem
públicos, só com PKCE.
Sua conta: GET /v1/me
Escopo account:read. Devolve só isto — nada da lista de produtos, nenhum hash:
{
"id": 12345,
"nome": "Fulana de Tal",
"email": "[email protected]",
"assinante_calculos": true,
"google_sub": "109876543210987654321",
"zenadv": { "nivel": "essencial", "pacote": 644, "validade": "2026-11-15" }
}
| Campo | O que é |
|---|---|
assinante_calculos |
A conta tem plano vigente do Debit Atualiza (100) ou do Debit Cálculos (110). É a régua que decide a janela de 2 anos dos cálculos rodados por esta API (seção 5, "Janela do plano gratuito"): com false, avise o usuário antes de calcular período mais antigo. |
google_sub |
O sub da conta Google ligada à Debit (a Debit liga por sub ou por e-mail verificado pelo Google), ou null. |
zenadv |
Plano vigente do ZenAdv (produto 131): nivel essencial (grupo zenadv) ou escritorio (grupo zenadvPro), o pacote e a validade (AAAA-MM-DD). Sem plano → null. Conta corporativa sem plano próprio herda o do pagante. Desde 10/2026 o único plano à venda é a ZenAdv Assinatura (644 mensal, 645 anual — grupo zenadv, nivel: "essencial"); escritorio só aparece para quem ainda tem um 646/647 vigente, que saíram de venda. |
Responde com Cache-Control: no-store. Conta inexistente ou excluída → 404 ACCOUNT_NOT_FOUND.
No MCP: tool debit_get_account, mesmo conteúdo.
Créditos de IA do ZenAdv: GET /v1/me/creditos-zenadv
Escopo account:read. A Debit é o caixa do ZenAdv: o cliente compra créditos de IA no carrinho
da Debit (pacotes do grupo creditos-zenadv) e o ZenAdv lê aqui o que foi pago, para lançar na
carteira do escritório. A Debit não entrega nada desses pacotes — quem entrega é o ZenAdv, uma
vez por pedido.
{
"compras": [
{ "pedido": 352901, "pacote": 654, "valor_brl": 100, "pago_em": "2026-10-17T00:00:00-03:00" },
{ "pedido": 352310, "pacote": 655, "valor_brl": 500, "pago_em": "2026-10-02T00:00:00-03:00" }
]
}
| Campo | O que é |
|---|---|
pedido |
Id do pedido na Debit. É a chave de idempotência do lado de quem credita (o ZenAdv usa debit:pedido:<id>): um pedido = uma compra. |
pacote |
O pacote de crédito comprado (654 = R$ 100, 655 = R$ 500, 656 = R$ 1.000). Se o pedido trouxer mais de um pacote de crédito, é o primeiro. |
valor_brl |
O crédito concedido, em reais — a qtde do pacote —, não o valor cobrado (desconto ou cupom não mudam o crédito). Com mais de um pacote de crédito no mesmo pedido, a soma. |
pago_em |
A data em que o pagamento foi confirmado e o pedido liberado, em ISO-8601 com o offset de São Paulo. Precisão de dia: a Debit guarda só a data da liberação (AAAAMMDD), então a hora sai sempre 00:00:00. |
- Só pedidos liberados — pagos, e as compras de teste da equipe da Debit, que a cobrança entrega como um pagamento real. Pendente, negado e estornado não aparecem; pedido estornado depois de creditado some da lista, e o estorno do crédito é feito por quem creditou.
- Só pedidos da própria conta da credencial (nada do pagante de uma conta corporativa).
- Mais recentes primeiro, no máximo 200. Sem compras →
{ "compras": [] }. - Responde com
Cache-Control: no-store. Conta inexistente ou excluída →404 ACCOUNT_NOT_FOUND. - Fora do MCP, de propósito (seção 7).
dbt_live_ e dbt_test_: não existe sandbox
Se você tem uma chave dbt_test_, o prefixo é só um rótulo. Não há ambiente de testes: ela 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, o mês desse dia fica inteiro com a SELIC (essa ponta não é proporcionalizada), o índice volta a corrigir no dia 1º do mês seguinte até a data de atualização — que pode ir até o último índice publicado — e os juros voltam a correr. Parcela que vence depois do fim não recebe SELIC: é corrigida pelo índice desde a própria data. 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, prescrição e os ritos da prisão e da expropriação (art. 528) |
tabelasJudiciais |
✔ | ✔ | — | — | a série mensal da tabela e as faixas de juros |
cartaoPonto |
✔ | ✔ | — | — | espelho de ponto por mês, marcações, dias trabalhados, 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 |
✔ | ✔ | ✔ | — | dados do benefício, critérios, composição da tabela, diferenças por competência (13º e prescritas marcadas), sucumbências e resumo |
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. É a mesma régua que o site sempre anunciou em /precos, e vale para atualizacaoMonetaria e calculosJudiciais — mas o que acontece com o lançamento antigo não é igual nos dois:
| Tipo | Lançamento com data anterior à janela | Onde o bloqueio aparece |
|---|---|---|
calculosJudiciais |
entra no total pelo valor nominal — sem correção, juros, multa nem SELIC | bloqueio_assinatura na raiz do resultado |
atualizacaoMonetaria |
fica fora dos valores atualizados e do total (todas as rubricas da linha saem zeradas, com diaErro: 5) |
info.bloqueio_assinatura |
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.
Em atualizacaoMonetaria o bloco tem o mesmo formato, sem mensagem, e mora em info (desde 01/10/2026; também ausente quando nada foi bloqueado e sempre ausente para assinante). Cada linha atingida tem diaErro: 5 e resultado_total: 0:
{
"info": {
"bloqueio_assinatura": {
"aplicado": true,
"anos": 2,
"dia_minimo": "01/10/2024",
"dia_minimo_int": 20241001,
"linhas": [ { "dia": "01/01/2020", "valor": 5000, "desc": "Parcela do acordo", "custas": false } ]
}
}
}
O demonstrativo (HTML, Word e PDF) ganha a seção "Valores fora da versão gratuita", antes das parcelas, com uma frase neutra e a lista dos valores que não entraram. O lançamento bloqueado fica fora de todos os totais, inclusive do nominal (info.soma_resultado_desatualizado, linha "Valores sem atualização" do resumo) — até 01/10/2026 ele continuava somado ali.
⚠️ O atalho
POST /v1/correctainda não repassa esse bloco: o item bloqueado volta comcorrected: 0e sem motivo. Para saber se houve bloqueio, use o fluxocalc+run.
⚠️ Em
calculosJudiciais, 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. EmatualizacaoMonetariao motor não olha o sinal: o valor negativo anterior à janela também fica fora, e aparece eminfo.bloqueio_assinatura.linhascomo qualquer outro.
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.
Pensão alimentícia: prescrição e ritos do art. 528
Prescrição — parametrosAtualizacao.prescricao.modo:
| valor | o que faz |
|---|---|
bienal (padrão) |
risca as parcelas vencidas há mais de 2 anos (art. 206, § 2º, do CC), contados da data-base ou da citação (considerar_em_citacao) |
quinquenal |
o mesmo, com 5 anos |
nenhuma |
não risca nada. A prescrição não corre contra filho menor sob poder familiar nem contra absolutamente incapaz (arts. 197, II, e 198, I, do CC) |
⚠️ O padrão continua bienal. Para filho menor, mande nenhuma: com o corte de 2 anos o
total sai menor que o devido, com HTTP 200. Cessado o poder familiar (em regra, aos 18
anos), o prazo passa a correr — para alimentando já maior, confira as parcelas antigas. O
resultado traz prescricao_modo e prescricao_data_corte (null em nenhuma); o laudo imprime
"Prescrição: não aplicada (arts. 197, II, e 198, I, do CC)".
Ritos do art. 528 — processo.data_ajuizamento_execucao (opcional, DD/MM/AAAA; null apaga):
subtotal_528_caput= rito da prisão (art. 528, §§ 3º e 7º, do CPC; Súmula 309 do STJ): as 3 prestações vencidas antes do ajuizamento da execução e todas as vencidas dele até a data-base, sem teto (mais as vincendas do mês da data-base).subtotal_528_p8= rito da expropriação (art. 528, § 8º, c/c art. 523 do CPC): as demais vencidas.- Sem a data — ou com data posterior à data-base — o recorte é pelas 3 últimas antes da
data-base, o comportamento anterior. O resultado diz qual foi usado:
rito_prisao_criterio(ajuizamento|data_base),rito_prisao_marcoerito_prisao_nota("Data do ajuizamento não informada: recorte pelas 3 últimas antes da data-base."). - Os dois subtotais são uma partição:
ids_rito_prisaoeids_rito_expropriacaonão se repetem e somamdebito_total_atualizado. Parcela prescrita não entra em nenhum dos dois. - A seleção é pelo tempo, não pela quitação: com a imputação retroativa, o pagamento abate primeiro as vencidas mais antigas (em regra, a expropriação), e a parcela quitada continua no rito em que estava, com saldo zero.
Ao atualizar uma execução já ajuizada sem informar a data, as parcelas vencidas no curso do processo caem na expropriação: o subtotal da prisão sai menor e o da expropriação, maior.
Vencimento das prestações — fixacao.dia_vencimento (inteiro de 1 a 31; null volta ao padrão):
- É o dia do mês em que cada prestação vence, conforme a sentença ou o acordo. Sem a chave vale
10, que era o dia fixo antes de o campo existir (em 30/10/2026). Cálculos salvos sem a chave continuam no dia 10. - Mês sem o dia escolhido (29 a 31) vence no último dia do mês: com dia
31, fevereiro/2024 vence em29/02/2024. - A 1ª prestação nunca vence antes do início da vigência: vigência em
27/09/2022com dia20dá27/09/2022,20/10/2022,20/11/2022… lista[].dia_vencimentoé derivado: o motor o reescreve a cadarun. Mandá-lo emlistanão tem efeito.- Prestação vencida é a que vence até a data-base, inclusive, em todos os modos de imputação.
Com data-base
01/10/2026e dia20, a de 10/2026 é vincenda: continua no débito e no rito da prisão, mas as "3 últimas antes da data-base" são 07, 08 e 09/2026. Até 30/10/2026 o modocompetenciacontava a do mês da data-base como vencida sempre que houvesse diferença. - O dia pesa no valor quando há data do ajuizamento (decide se a prestação do mês do ajuizamento é
anterior a ele) e nos modos
retroativa/prospectiva(ordem da imputação). Correção sem pro rata e juros de 1% contam só mês e ano.
Destaques de valores
- pensaoAlimenticia →
fixacao.tipo:percentual_sm,valor_fixo,percentual_liquido,percentual_bruto,mista. - pensaoAlimenticia →
parametrosAtualizacao.prescricao.modo:bienal(padrão),quinquenal,nenhuma(filho menor sob poder familiar ou absolutamente incapaz — arts. 197, II, e 198, I, do CC). Ver a seção acima. - pensaoAlimenticia →
fixacao.dia_vencimento:1a31(padrão10). Último dia do mês quando o mês não tem o dia; a 1ª prestação nunca antes do início da vigência. Ver a seção acima. - 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. - prevDifNRecebidas →
dataAtualejurosTab: a tabela é cortada nadataAtual, como no Cálculo Judicial: com data no passado, correção, SELIC e juros param no mês anterior ao dela, e não até hoje. Os juros dojurosTabnão correm nos meses em que a tabela corrige pela SELIC, porque a SELIC da EC 113/2021 já inclui os juros. Se não tirar nada, a resposta trazjurosSelic: null; se tirar, trazjurosSelic: {inicio, fim}, com os meses no formatoano × 12 + mês. - prevDifNRecebidas → honorários (desde 21/10/2026): em
condenacaoSentenca/condenacaoAcordaoo honorário é% × base até a data— antes somava de novo os juros e a Selic de todas as parcelas.honoCompPercentualvale (era 10% fixo; ausente, segue 10%). SemhonoSucumModo, valecausa, que é o que a tela mostra; emcausasemhonoSucumValorCausanão há linha de honorário, e com valor a data éhonoSucumDiaAjuzuizamentoou, sem ela,dataAjuizamento. Linha desucumListsem valor é ignorada. A resposta traz tambémtabelaNomeevalores.colunas(letras e fórmulas do demonstrativo). - 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 →
reducaoHoraNoturna: padrão true — a hora noturna conta 52 min 30 s (art. 73, § 1º, da CLT), cada minuto noturno vale 8/7; a ausência da chave também reduz.falseé para quem não tem a redução (rural, Lei 5.889/73, ou norma coletiva). Cada período do resultado trazdiasTrabalhados: dias com marcação de trabalho, mesmo incompleta; falta e férias não contam. - cartaoPonto →
jornadas(metodologias):ate10…ate60são os percentuais de cada faixa de 10 horas extras da semana (ate10= 1ª à 10ª hora extra). Até 29/10/2026 eles eram ignorados e a semana saía no percentual de folga (100%); hoje valem, e vale a linha cujoinicio/fimcontém o dia. - 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).iof_modo(saldo devedor e tabelas de financiamento):legal= Decreto 6.306/2007 — alíquota diária vigente na data do contrato sobre a amortização de cada parcela, até 365 dias, mais o adicional de 0,38% sobre o principal, calculado uma vez na contratação (memória emresultado.iof_legal);percentual= o percentual livre deiof_perc, aplicado mês a mês sobre as bases marcadas, que não é o IOF legal. Sem a chave, valepercentual(cálculos antigos não mudam de número). Cálculo novo nasce comiof: falseeiof_modo: 'legal';iof_pessoa(PF|PJ) eiof_financiado(padrãotrue) só valem no modo legal.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.
Só para assinantes, sem exceção. Como toda a API (seção 1), a extração por IA exige plano Debit Atualiza, Trabalhista ou Cálculos (100, 101 ou 110) vigente na própria conta — aqui a regra vale também para os aplicativos parceiros liberados. Sem ela a resposta é
403 SUBSCRIPTION_REQUIRED, antes de a IA ler o documento; repetir não adianta. Oassinante_calculosdeGET /v1/mejá diz que a conta extrai (ele cobre 100 e 110); só quem assina apenas o Trabalhista (101) extrai com ele emfalse.
POST /v1/extract (escopo extract:run) lê CNIS, sentença, cartão de ponto, doc trabalhista ou contrato bancário:
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 | contrato. 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, debit_get_account (a mesma resposta de GET /v1/me).
Ficam fora do MCP, de propósito: /v1/keys (a chave sairia em texto no contexto do agente), /v1/auth e as telas do OAuth (login por tool faria o agente manipular senha — o fluxo OAuth existe para evitar isso), e /v1/me/creditos-zenadv (é o contrato de integração do caixa do ZenAdv — o aplicativo lê o pago para creditar a carteira do escritório —, não uma pergunta que um agente faça à conta Debit; uma tool a mais pesaria no contexto de todo conector sem servir a nenhum).
Conectores remotos (Claude/ChatGPT) descobrem o OAuth via /.well-known/oauth-authorization-server e abrem o "Entrar com Debit" (seção 1).
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. |
INVALID_REFRESH |
401 | POST /v1/auth/refresh com refresh inválido, expirado, já usado — ou do OAuth: esse renova só no /token, pelo client que o recebeu. |
ACCOUNT_NOT_FOUND |
404 | GET /v1/me ou GET /v1/me/creditos-zenadv de conta inexistente ou excluída. |
NOT_ALLOWED |
401 | Credencial válida, conta fora da liberação (fase de testes). Fale com o suporte. |
FORBIDDEN_SCOPE |
403 | A credencial não tem o escopo da operação. A chave criada no site tem todos; num conector OAuth, reconecte autorizando o escopo. |
HUMAN_ONLY |
403 | Listar e revogar chaves exige login por JWT — uma chave não gerencia 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. Desde 22/09/2026 só sobra para a recusa sem motivo declarado: tabela oficial, janela da versão gratuita e arquivo expurgado passaram a ter código próprio (as três linhas abaixo). |
OFFICIAL_TABLE_READ_ONLY |
409 | PATCH/run numa das tabelas judiciais do catálogo da debit (CJF, tribunais). Elas são só-leitura para todo mundo: alterá-las mudaria o resultado de todo cálculo apontado para elas. Clone a tabela no site e use o id da sua cópia. |
CALC_NOT_EDITABLE |
409 | O cálculo está fora da janela de edição da versão gratuita. Ele continua podendo ser lido, rodado e exportado — só não alterado. Uma assinatura ativa remove a janela. |
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, alterar nem exportar. Cálculos antigos podem ter o arquivo expurgado. Desde 22/09/2026 também no PATCH e no run, que antes devolviam FIELD_REJECTED/ENGINE_REJECTED culpando o campo. |
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. |
SUBSCRIPTION_REQUIRED |
403 | A conta não tem assinatura ativa: desde 28/10/2026 a API é exclusiva para assinantes (seção 1). GET /v1/me continua respondendo. Não é falha passageira: repetir dá o mesmo até a conta assinar. |
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}. | |KEY_CREATION_REMOVED| 410 |POST /v1/keys: a API não cria mais chaves (desde 16/10/2026). Crie no site, menu → API. | |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.