finstatdocs
API Entrar

Referência da API

A API /v1 recebe o PDF, informa a situação e entrega o resultado liberado. Toda chamada usa HTTPS e envia Authorization: Bearer com uma chave de API. Respostas e erros são JSON; erros sempre no formato {"error": "<código>"}.

Esta página é gerada do contrato OpenAPI 3.1, o mesmo servido em /v1/openapi.json.

URL base

https://finstat.com.br

URL base
https://finstat.com.br/v1
Erro
{
  "error": "unauthorized"
}

Enviar documento

POST/v1/documents

Envia o PDF bruto de um balanço/DRE. A resposta 202 traz o id e a situação inicial (queued). O resultado fica disponível na liberação, depois da conferência humana quando ela é necessária: acompanhe pelo webhook ou por Consultar documento.

Mesma Idempotency-Key e mesma entrada devolvem o mesmo id, sem criar outro documento nem nova cobrança. Veja Enviar documento.

Escopo: documents:write

Parâmetros de consulta

cnpjstringobrigatório
CNPJ da empresa do documento, 14 caracteres sem pontuação (dígitos ou letras maiúsculas; aceita o CNPJ alfanumérico).

14 caracteres · formato ^[A-Z0-9]{12}[0-9]{2}$

period_endstring (date)obrigatório
Data de encerramento do período, AAAA-MM-DD.
entityenum
Entidade das demonstrações: Individual (padrão), Controladora, Consolidado ou Combinado.

valores: Individual, Controladora, Consolidado, Combinado · padrão: "Individual"

Cabeçalhos

Authorizationstringobrigatório
Bearer fst_..., chave com o escopo documents:write.
Idempotency-Keystringobrigatório
Obrigatório. 1 a 128 caracteres, único na sua empresa. Derive do seu registro (por exemplo, o id do lote) e repita a mesma chave em toda nova tentativa.

1 a 128 caracteres

Corpo

application/pdf

O PDF bruto, com Content-Type: application/pdf, até 25 MiB e 100 páginas. Sem multipart nem base64.

Respostas

  • 202Documento aceito (ou o mesmo de antes, se repetido com a mesma chave).
  • 401unauthorized: chave ausente, inválida, revogada, expirada ou sem o escopo
  • 409version_conflict: Idempotency-Key já usada com outra entrada.
  • 413pdf_too_large ou body_too_large.
  • 422pdf_and_idempotency_key_required, invalid_pdf ou invalid_request.
  • 429too_many_requests: sua chave já tem dois envios em andamento; vem com Retry-After. Repita com a mesma Idempotency-Key.
  • 4XXOutro erro do cliente, no mesmo formato.
  • 500internal_error: repita com a mesma Idempotency-Key.
  • 503capacity_busy: espere Retry-After e repita.
curl
curl "https://finstat.com.br/v1/documents?cnpj=00000000000191&period_end=2025-12-31&entity=Individual" \
  -H "Authorization: Bearer $FINSTAT_API_KEY" \
  -H "Idempotency-Key: lote-2025-12-0042" \
  -H "Content-Type: application/pdf" \
  --data-binary @balanco.pdf
Node
import { Finstat } from "finstat";

const finstat = new Finstat(process.env.FINSTAT_API_KEY!);

import { readFile } from "node:fs/promises";

const document = await finstat.documents.submit(
  {
    file: await readFile("balanco.pdf"),
    cnpj: "00000000000191",
    periodEnd: "2025-12-31",
    entity: "Individual",
  },
  // Opcional: sem ela, o SDK deriva a chave do conteúdo do PDF.
  { idempotencyKey: "lote-2025-12-0042" },
);
console.log(document.id, document.status); // "queued"
Python
import os
from pathlib import Path

import httpx

response = httpx.post(
    "https://finstat.com.br/v1/documents",
    params={
        "cnpj": "00000000000191",
        "period_end": "2025-12-31",
        "entity": "Individual",
    },
    headers={
        "Authorization": f"Bearer {os.environ['FINSTAT_API_KEY']}",
        "Idempotency-Key": "lote-2025-12-0042",
        "Content-Type": "application/pdf",
    },
    content=Path("balanco.pdf").read_bytes(),
    timeout=60,
)
response.raise_for_status()
print(response.json())
Resposta 202
{
  "id": "00000000-0000-4000-8000-000000000001",
  "status": "queued",
  "reason": null,
  "pages": 0,
  "processing_seconds": 0,
  "engine_version": "",
  "model_version": ""
}

Consultar documento

GET/v1/documents/{job_id}

Devolve a situação do documento, o motivo (reason), as páginas, o tempo de processamento e as versões. Pode ser repetida à vontade; prefira o webhook para não consultar em laço curto.

Escopo: documents:read

Parâmetros de caminho

job_idstringobrigatório
Id do documento, devolvido no envio (id).

Cabeçalhos

Authorizationstringobrigatório
Bearer fst_..., chave com o escopo documents:read.

Respostas

  • 200Situação atual do documento.
  • 401unauthorized: chave ausente, inválida, revogada, expirada ou sem o escopo
  • 404not_found: documento inexistente ou de outra empresa.
  • 4XXOutro erro do cliente, no mesmo formato.
  • 500internal_error: repita com a mesma Idempotency-Key.
  • 503capacity_busy: espere Retry-After e repita.
curl
curl "https://finstat.com.br/v1/documents/00000000-0000-4000-8000-000000000001" \
  -H "Authorization: Bearer $FINSTAT_API_KEY"
Node
import { Finstat } from "finstat";

const finstat = new Finstat(process.env.FINSTAT_API_KEY!);

const document = await finstat.documents.retrieve("00000000-0000-4000-8000-000000000001");
console.log(document.status, document.reason);
Python
import os

import httpx

response = httpx.get(
    "https://finstat.com.br/v1/documents/00000000-0000-4000-8000-000000000001",
    headers={
        "Authorization": f"Bearer {os.environ['FINSTAT_API_KEY']}",
    },
    timeout=60,
)
response.raise_for_status()
print(response.json())
Resposta 200
{
  "id": "00000000-0000-4000-8000-000000000001",
  "status": "review",
  "reason": null,
  "pages": 12,
  "processing_seconds": 41.5,
  "engine_version": "1.0.0",
  "model_version": "1.0.0"
}

Buscar resultado

GET/v1/documents/{job_id}/result

Devolve o histórico liberado só deste documento. Antes da liberação responde 409 not_completed. Formato em Resultado e histórico.

Escopo: documents:read

Parâmetros de caminho

job_idstringobrigatório
Id do documento, devolvido no envio (id).

Cabeçalhos

Authorizationstringobrigatório
Bearer fst_..., chave com o escopo documents:read.

Respostas

  • 200Histórico liberado do documento.
  • 401unauthorized: chave ausente, inválida, revogada, expirada ou sem o escopo
  • 404not_found: documento inexistente ou de outra empresa.
  • 409not_completed: resultado antes da liberação.
  • 4XXOutro erro do cliente, no mesmo formato.
  • 500internal_error: repita com a mesma Idempotency-Key.
  • 503capacity_busy: espere Retry-After e repita.
curl
curl "https://finstat.com.br/v1/documents/00000000-0000-4000-8000-000000000001/result" \
  -H "Authorization: Bearer $FINSTAT_API_KEY"
Node
import { Finstat } from "finstat";

const finstat = new Finstat(process.env.FINSTAT_API_KEY!);

import { FinstatNotReadyError } from "finstat";

try {
  const history = await finstat.documents.result("00000000-0000-4000-8000-000000000001");
  for (const [period, entries] of Object.entries(history)) {
    console.log(period, entries.length);
  }
} catch (error) {
  if (!(error instanceof FinstatNotReadyError)) throw error;
  // Ainda em conferência: espere o webhook "completed".
}
Python
import os

import httpx

response = httpx.get(
    "https://finstat.com.br/v1/documents/00000000-0000-4000-8000-000000000001/result",
    headers={
        "Authorization": f"Bearer {os.environ['FINSTAT_API_KEY']}",
    },
    timeout=60,
)
response.raise_for_status()
print(response.json())
Resposta 200
{
  "Individual - 31/12/2025 - ": [
    {
      "termo_total": "ac - caixa e equivalentes",
      "valor": "152340.75",
      "moeda": "BRL",
      "escala": "1",
      "tipo": "balanco",
      "section": "ac",
      "subsection": "",
      "data": "31/12/2025",
      "data_ano": "2025",
      "data_init": "",
      "page": 2,
      "bbox_left": 0.62,
      "bbox_top": 0.214,
      "bbox_width": 0.12,
      "bbox_height": 0.015,
      "x": 0.62,
      "y": 0.214,
      "conf": 1,
      "tipo_balanco": "Individual",
      "consolidado": false,
      "empresa": "Empresa Exemplo Ltda",
      "cnpj": "00000000000191",
      "id": "00000000-0000-4000-8000-000000000001-0",
      "unique_id": "00000000-0000-4000-8000-000000000001-0",
      "parent": "",
      "is_total": 0,
      "formula": "",
      "tempo": "",
      "over_threshold_h": 0,
      "over_threshold_v": 0
    },
    {
      "termo_total": "dre - receita bruta",
      "valor": "1250000.00",
      "moeda": "BRL",
      "escala": "1",
      "tipo": "dre",
      "section": "dre",
      "subsection": "",
      "data": "31/12/2025",
      "data_ano": "2025",
      "data_init": "",
      "page": 4,
      "bbox_left": 0.62,
      "bbox_top": 0.188,
      "bbox_width": 0.12,
      "bbox_height": 0.015,
      "x": 0.62,
      "y": 0.188,
      "conf": 1,
      "tipo_balanco": "Individual",
      "consolidado": false,
      "empresa": "Empresa Exemplo Ltda",
      "cnpj": "00000000000191",
      "id": "00000000-0000-4000-8000-000000000001-1",
      "unique_id": "00000000-0000-4000-8000-000000000001-1",
      "parent": "",
      "is_total": 0,
      "formula": "",
      "tempo": "",
      "over_threshold_h": 0,
      "over_threshold_v": 0
    }
  ]
}

Consultar histórico do CNPJ

GET/v1/history/{cnpj}

Junta os documentos liberados deste CNPJ na sua empresa, por entidade e data. Responde {} quando não há liberação. Durante uma nova conferência, continua com a última versão liberada.

Escopo: documents:read

Parâmetros de caminho

cnpjstringobrigatório
CNPJ, 14 caracteres sem pontuação.

Cabeçalhos

Authorizationstringobrigatório
Bearer fst_..., chave com o escopo documents:read.

Respostas

  • 200Histórico liberado do CNPJ ({} quando não há).
  • 401unauthorized: chave ausente, inválida, revogada, expirada ou sem o escopo
  • 4XXOutro erro do cliente, no mesmo formato.
  • 500internal_error: repita com a mesma Idempotency-Key.
  • 503capacity_busy: espere Retry-After e repita.
curl
curl "https://finstat.com.br/v1/history/00000000000191" \
  -H "Authorization: Bearer $FINSTAT_API_KEY"
Node
import { Finstat } from "finstat";

const finstat = new Finstat(process.env.FINSTAT_API_KEY!);

const history = await finstat.history.retrieve("00000000000191");
Python
import os

import httpx

response = httpx.get(
    "https://finstat.com.br/v1/history/00000000000191",
    headers={
        "Authorization": f"Bearer {os.environ['FINSTAT_API_KEY']}",
    },
    timeout=60,
)
response.raise_for_status()
print(response.json())
Resposta 200
{
  "Individual - 31/12/2025 - ": [
    {
      "termo_total": "ac - caixa e equivalentes",
      "valor": "152340.75",
      "moeda": "BRL",
      "escala": "1",
      "tipo": "balanco",
      "section": "ac",
      "subsection": "",
      "data": "31/12/2025",
      "data_ano": "2025",
      "data_init": "",
      "page": 2,
      "bbox_left": 0.62,
      "bbox_top": 0.214,
      "bbox_width": 0.12,
      "bbox_height": 0.015,
      "x": 0.62,
      "y": 0.214,
      "conf": 1,
      "tipo_balanco": "Individual",
      "consolidado": false,
      "empresa": "Empresa Exemplo Ltda",
      "cnpj": "00000000000191",
      "id": "00000000-0000-4000-8000-000000000001-0",
      "unique_id": "00000000-0000-4000-8000-000000000001-0",
      "parent": "",
      "is_total": 0,
      "formula": "",
      "tempo": "",
      "over_threshold_h": 0,
      "over_threshold_v": 0
    },
    {
      "termo_total": "dre - receita bruta",
      "valor": "1250000.00",
      "moeda": "BRL",
      "escala": "1",
      "tipo": "dre",
      "section": "dre",
      "subsection": "",
      "data": "31/12/2025",
      "data_ano": "2025",
      "data_init": "",
      "page": 4,
      "bbox_left": 0.62,
      "bbox_top": 0.188,
      "bbox_width": 0.12,
      "bbox_height": 0.015,
      "x": 0.62,
      "y": 0.188,
      "conf": 1,
      "tipo_balanco": "Individual",
      "consolidado": false,
      "empresa": "Empresa Exemplo Ltda",
      "cnpj": "00000000000191",
      "id": "00000000-0000-4000-8000-000000000001-1",
      "unique_id": "00000000-0000-4000-8000-000000000001-1",
      "parent": "",
      "is_total": 0,
      "formula": "",
      "tempo": "",
      "over_threshold_h": 0,
      "over_threshold_v": 0
    }
  ]
}

Objetos

DocumentStatus

Resposta do envio e da consulta de documento.

idstringobrigatório
Id do documento.
statusJobStatusobrigatório
Situação: queued, processing, review, completed, rejected ou error.
reasonstring | nullobrigatório
Motivo da situação, quando houver; null caso contrário. Veja Situações.
pagesintegerobrigatório
Páginas do PDF (0 antes do processamento).
processing_secondsnumberobrigatório
Tempo de processamento, em segundos.
engine_versionstring
Versão de processamento que gerou a extração (vazia antes dela).
model_versionstring
Versão complementar de processamento (vazia antes dela).

HistoryEntry

Uma linha do histórico. O histórico (History) é um objeto cuja chave junta entidade e data (Individual - 31/12/2025 - ) e cujo valor é uma lista de HistoryEntry.

tempostring
Reservado; hoje vazio.
confnumber
1 indica conferência humana. Não é probabilidade.
datastringobrigatório
Data do período, dd/mm/aaaa.
data_anostringobrigatório
Ano do período.
termo_totalstringobrigatório
A conta, um dos termos (TermoTotal).
valorstringobrigatório
String decimal com duas casas, em reais. Não converta para float.
pageintegerobrigatório
Página do PDF onde está o valor, começando em 1.
idstringobrigatório
Id da linha: o id do documento seguido de - e um número.
subsectionstring
Reservado; hoje vazio.
tipostringobrigatório
balanco ou dre.
sectionstringobrigatório
Grupo do termo: o prefixo de termo_total (ac, pc, dre...).
moedastring
Moeda, BRL.
escalastring
Escala do valor; 1 indica que valor já está em reais.
empresastringobrigatório
Nome da empresa.
cnpjstringobrigatório
CNPJ informado no envio.
consolidadobooleanobrigatório
true quando a entidade é Consolidado.
tipo_balancoenumobrigatório
Entidade: Individual, Controladora, Consolidado ou Combinado.
ynumberobrigatório
Igual a bbox_top (compatibilidade).
xnumberobrigatório
Igual a bbox_left (compatibilidade).
unique_idstringobrigatório
Igual a id (compatibilidade).
parentstring
Reservado; hoje vazio.
is_totalinteger
Reservado; hoje 0.
over_threshold_hinteger
Reservado; hoje 0.
over_threshold_vinteger
Reservado; hoje 0.
bbox_leftnumberobrigatório
Borda esquerda do valor, em fração da largura da página (0 a 1).
bbox_topnumberobrigatório
Borda superior do valor, em fração da altura da página (0 a 1).
bbox_heightnumberobrigatório
Altura do valor, em fração da altura da página.
bbox_widthnumberobrigatório
Largura do valor, em fração da largura da página.
data_initstring
Reservado; hoje vazio.
formulastring
Reservado; hoje vazio.

ApiError

Corpo de todo erro da API.

errorstringobrigatório
Código estável do erro. Nunca ecoa o que você enviou. Veja Erros.