TOPO · Desenvolvedores

Referência da API

Cada rota da API v1, com os campos, os exemplos e o significado de cada resposta.

Esta página é gerada do contrato da API (openapi-v1.json), o mesmo arquivo que a API confere a cada mudança. Cada rota mostra para que serve, os campos do pedido, a resposta de sucesso e o que cada erro quer dizer.

Para começar do zero, leia antes a primeira chamada e a autenticação.

Listar balancetes

GET/api/v1/trial-balances

Lista os balancetes importados, com competência, versão, status e quem importou. Filtre por companyId e por period (AAAA-MM, por exemplo 2026-08). Serve para conferir se o balancete que o ERP enviou chegou e foi liberado. Escopo: trial_balances:read.

A resposta vem em páginas: data traz as linhas e pagination diz a página, o tamanho, o total de linhas e o total de páginas. O padrão é 50 linhas por página, e o máximo é 100 (limit). Para ler tudo, repita a chamada com page=1, page=2 e assim por diante, até pagination.pages. Limite: 30 chamadas por minuto por rota.

Autenticação

CabeçalhoBearer <chave>

Authorization: Bearer

Enviado em: header

Parâmetros da URL

page?number

Página, a partir de 1.

limit?number

Linhas por página, de 1 a 100. Padrão 50.

companyId?number

Id da empresa no TOPO.

period?string

Competência, no formato AAAA-MM.

Corpo da resposta

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/v1/trial-balances"
{  "data": [    {      "id": 318,      "empresaId": 12,      "empresaNome": "Transportes Exemplo Ltda",      "competencia": "2026-08",      "versao": 2,      "status": "RELEASED",      "importadoEm": "2026-09-03T14:12:05.000Z",      "importadoPor": "Chave de API SAP balancete (a1B2c3D4e5F6g7H8)",      "linhas": 474    }  ],  "pagination": {    "page": 1,    "limit": 50,    "total": 132,    "pages": 3  }}

Importar balancete

POST/api/v1/trial-balances

Envia o balancete de uma competência em JSON, direto do ERP, sem planilha. Informe a empresa por companyId ou por cnpj, a competência em period (AAAA-MM) e as linhas em lineItems, até 20.000 por chamada. A resposta diz quantas linhas vieram, quantas entraram e por que as outras ficaram de fora; avisos não impedem a importação. Escopo: trial_balances:write. Limite: 30 chamadas por minuto.

O que acontece no TOPO: o balancete entra na competência da empresa com as mesmas validações da tela (plano de contas, natureza dos saldos, continuidade com o mês anterior) e fica pronto para o cliente liberar as conciliações. Reenviar o mesmo conteúdo não duplica nada: a resposta é 200 com reenvio: true. Conteúdo diferente na mesma competência cria uma versão nova.

Autenticação

CabeçalhoBearer <chave>

Authorization: Bearer

Enviado em: header

Corpo do pedido

application/json

Tipos em TypeScript

Use o tipo request body em TypeScript.

Corpo da resposta

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/api/v1/trial-balances" \  -H "Content-Type: application/json" \  -d '{    "companyId": 12,    "cnpj": "12.345.678/0001-90",    "period": "2026-09",    "chartName": "Plano de Contas Divisão Logística",    "lineItems": [      {        "accountCode": "1.1.01.001",        "accountName": "Caixa Geral",        "previousBalance": 1000.5,        "debit": 250,        "credit": 100,        "finalBalance": 1150.5      }    ]  }'
{  "success": true,  "data": {    "reenvio": false,    "trialBalanceId": 318,    "enviadas": 474,    "importadas": 207,    "ignoradasForaDoPlano": 3,    "ignoradasQueNaoConciliam": 264,    "avisos": [      "Saldo anterior da conta 1.1.01 diferente do saldo final do mês anterior"    ]  }}

Importar balancete por arquivo

POST/api/v1/trial-balances/arquivo

Envia o mesmo relatório que o usuário subiria na tela, no campo file de um formulário multipart, com cnpj ou companyId. Use quando o ERP já gera o arquivo e montar o JSON dá mais trabalho. Vale o mapeamento de colunas salvo para a empresa na tela de importação. Competência e plano de contas saem do arquivo quando não vêm no formulário. Escopo: trial_balances:write. Limite: 30 chamadas por minuto.

O que acontece no TOPO: o balancete entra na competência da empresa com as mesmas validações da tela (plano de contas, natureza dos saldos, continuidade com o mês anterior) e fica pronto para o cliente liberar as conciliações. Reenviar o mesmo conteúdo não duplica nada: a resposta é 200 com reenvio: true. Conteúdo diferente na mesma competência cria uma versão nova.

Autenticação

CabeçalhoBearer <chave>

Authorization: Bearer

Enviado em: header

Corpo do pedido

multipart/form-data

Tipos em TypeScript

Use o tipo request body em TypeScript.

Corpo da resposta

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/api/v1/trial-balances/arquivo" \  -F file="string"
{  "success": true,  "data": {    "reenvio": false,    "trialBalanceId": 318,    "enviadas": 474,    "importadas": 207,    "ignoradasForaDoPlano": 3,    "ignoradasQueNaoConciliam": 264,    "avisos": [      "Saldo anterior da conta 1.1.01 diferente do saldo final do mês anterior"    ]  }}

Listar empresas

GET/api/v1/companies

Lista as empresas do cliente da chave, com razão social, CNPJ e regime tributário. Use no começo da integração para descobrir o id de cada empresa, que as outras rotas pedem em companyId. Só lê: nada muda no TOPO. Escopo: companies:read.

A resposta vem em páginas: data traz as linhas e pagination diz a página, o tamanho, o total de linhas e o total de páginas. O padrão é 50 linhas por página, e o máximo é 100 (limit). Para ler tudo, repita a chamada com page=1, page=2 e assim por diante, até pagination.pages. Limite: 30 chamadas por minuto por rota.

Autenticação

CabeçalhoBearer <chave>

Authorization: Bearer

Enviado em: header

Parâmetros da URL

page?number

Página, a partir de 1.

limit?number

Linhas por página, de 1 a 100. Padrão 50.

Corpo da resposta

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/v1/companies"
{  "data": [    {      "id": 12,      "razaoSocial": "Transportes Exemplo Ltda",      "nomeFantasia": "Exemplo Logística",      "cnpj": "12345678000190",      "regimeTributario": "REAL_PROFIT",      "status": "ACTIVE",      "empresaControladoraId": null    }  ],  "pagination": {    "page": 1,    "limit": 50,    "total": 132,    "pages": 3  }}
GET/api/v1/chart-of-accounts

Lista os planos de contas da empresa informada em companyId (obrigatório). Uma empresa pode ter mais de um plano ativo; o balancete diz qual usar. Use o id do plano para ler as contas em /api/v1/chart-of-accounts/{id}/accounts. Escopo: chart_of_accounts:read.

A resposta vem em páginas: data traz as linhas e pagination diz a página, o tamanho, o total de linhas e o total de páginas. O padrão é 50 linhas por página, e o máximo é 100 (limit). Para ler tudo, repita a chamada com page=1, page=2 e assim por diante, até pagination.pages. Limite: 30 chamadas por minuto por rota.

Autenticação

CabeçalhoBearer <chave>

Authorization: Bearer

Enviado em: header

Parâmetros da URL

page?number

Página, a partir de 1.

limit?number

Linhas por página, de 1 a 100. Padrão 50.

companyId*number

Id da empresa no TOPO.

Corpo da resposta

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/v1/chart-of-accounts?companyId=0"
{  "data": [    {      "id": 4,      "empresaId": 12,      "nome": "Plano de Contas Divisão Logística",      "vigenciaInicio": "2026-01-01",      "vigenciaFim": null,      "ativo": true,      "versao": 1    }  ],  "pagination": {    "page": 1,    "limit": 50,    "total": 132,    "pages": 3  }}

Listar contas de um plano

GET/api/v1/chart-of-accounts/{id}/accounts

Lista as contas do plano id, com código, código reduzido, natureza e se a conta entra na conciliação. Filtre por empresa com companyId. Útil para montar o de-para entre o plano do ERP e o do TOPO antes de enviar o balancete. Escopo: chart_of_accounts:read.

A resposta vem em páginas: data traz as linhas e pagination diz a página, o tamanho, o total de linhas e o total de páginas. O padrão é 50 linhas por página, e o máximo é 100 (limit). Para ler tudo, repita a chamada com page=1, page=2 e assim por diante, até pagination.pages. Limite: 30 chamadas por minuto por rota.

Autenticação

CabeçalhoBearer <chave>

Authorization: Bearer

Enviado em: header

Parâmetros do caminho

id*number

Id do plano de contas, o id que GET /api/v1/chart-of-accounts devolve.

Parâmetros da URL

page?number

Página, a partir de 1.

limit?number

Linhas por página, de 1 a 100. Padrão 50.

companyId?number

Id da empresa no TOPO.

Corpo da resposta

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/v1/chart-of-accounts/0/accounts"
{  "data": [    {      "id": 881,      "planoId": 4,      "empresaId": 12,      "codigo": "1.1.01.001",      "codigoReduzido": "1001",      "descricao": "Caixa Geral",      "tipo": "ANALYTICAL",      "natureza": "DEBIT",      "classificacao": "Ativo Circulante",      "departamento": "Financeiro",      "setor": "Tesouraria",      "exigeConciliacao": true    }  ],  "pagination": {    "page": 1,    "limit": 50,    "total": 132,    "pages": 3  }}

Linhas de um balancete

GET/api/v1/trial-balances/{id}/lines

Devolve as linhas do balancete id: conta, saldo anterior, débito, crédito e saldo final. Pegue o id na lista de balancetes. É a rota que o Power BI usa para montar a tabela de saldos. Escopo: trial_balances:read.

A resposta vem em páginas: data traz as linhas e pagination diz a página, o tamanho, o total de linhas e o total de páginas. O padrão é 50 linhas por página, e o máximo é 100 (limit). Para ler tudo, repita a chamada com page=1, page=2 e assim por diante, até pagination.pages. Limite: 30 chamadas por minuto por rota.

Autenticação

CabeçalhoBearer <chave>

Authorization: Bearer

Enviado em: header

Parâmetros do caminho

id*number

Id do balancete, o id que GET /api/v1/trial-balances devolve.

Parâmetros da URL

page?number

Página, a partir de 1.

limit?number

Linhas por página, de 1 a 100. Padrão 50.

Corpo da resposta

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/v1/trial-balances/0/lines"
{  "data": [    {      "balanceteId": 318,      "empresaId": 12,      "competencia": "2026-08",      "contaCodigo": "1.1.01.001",      "contaDescricao": "Caixa Geral",      "saldoAnterior": 1000.5,      "debito": 250,      "credito": 100,      "saldoFinal": 1150.5    }  ],  "pagination": {    "page": 1,    "limit": 50,    "total": 132,    "pages": 3  }}

Listar conciliações

GET/api/v1/reconciliations

Lista as conciliações com status, responsável atual, prazo, situação do prazo (SLA) e os saldos contábil, conciliado e a diferença. Filtre por companyId e period. O responsável é o mesmo nome da coluna Responsável da tela. Escopo: reconciliations:read.

A resposta vem em páginas: data traz as linhas e pagination diz a página, o tamanho, o total de linhas e o total de páginas. O padrão é 50 linhas por página, e o máximo é 100 (limit). Para ler tudo, repita a chamada com page=1, page=2 e assim por diante, até pagination.pages. Limite: 30 chamadas por minuto por rota.

Autenticação

CabeçalhoBearer <chave>

Authorization: Bearer

Enviado em: header

Parâmetros da URL

page?number

Página, a partir de 1.

limit?number

Linhas por página, de 1 a 100. Padrão 50.

companyId?number

Id da empresa no TOPO.

period?string

Competência, no formato AAAA-MM.

Corpo da resposta

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/v1/reconciliations"
{  "data": [    {      "id": 5120,      "empresaId": 12,      "empresaNome": "Transportes Exemplo Ltda",      "competencia": "2026-08",      "contaId": 881,      "contaCodigo": "1.1.01.001",      "contaDescricao": "Caixa Geral",      "status": "IN_ELABORATION",      "responsavelNome": "Mariana Souza",      "responsavelPapel": "Elaborador",      "prazo": "2026-09-05T00:00:00.000Z",      "slaStatus": "ON_TIME",      "saldoContabil": 1150.5,      "saldoConciliado": 1150.5,      "diferenca": 0,      "ajustes": 0    }  ],  "pagination": {    "page": 1,    "limit": 50,    "total": 132,    "pages": 3  }}

Consulta GraphQL (só leitura)

POST/api/v1/graphql

Os mesmos dados da leitura REST numa chamada só: empresas, planosDeContas, contas, balancetes, linhasDoBalancete e conciliacoes, com os mesmos filtros e a mesma paginação. Envie um JSON com query e, se houver, variables, com o cabeçalho Content-Type: application/json. Não existe mutation: nada muda no TOPO.

Os erros seguem o formato GraphQL: a resposta traz errors, cada um com message em português e extensions.code. Códigos comuns: SO_LEITURA (mandou mutation), PROFUNDIDADE_EXCEDIDA e COMPLEXIDADE_EXCEDIDA (consulta grande demais: peça menos campos ou páginas menores) e CONTENT_TYPE_INVALIDO (status 415). Escopo: analytics:read. Limite: 30 chamadas por minuto.

Autenticação

CabeçalhoBearer <chave>

Authorization: Bearer

Enviado em: header

Corpo do pedido

application/json

Tipos em TypeScript

Use o tipo request body em TypeScript.

Corpo da resposta

application/json

curl -X POST "https://example.com/api/v1/graphql" \  -H "Content-Type: application/json" \  -d '{    "query": "query Saldos($empresa: Int!, $competencia: String!) {\\n  balancetes(companyId: $empresa, period: $competencia) {\\n    data { id competencia status linhas }\\n  }\\n}",    "variables": {      "empresa": 12,      "competencia": "2026-08"    }  }'
Vazio