SN Analytics: Comércio
Endpoints da WebApiAlcance para o faturamento de comércio do Simples Nacional, consumidos pelo produto Simples Analytics. O domínio tem dois níveis: o consolidado (total de faturamento por empresa e competência, calculado no servidor) e os registros individuais de NF-e que compõem cada consolidado. Toda escrita em registros recalcula automaticamente o consolidado da competência afetada - um consolidado que fica sem registros é apagado. Os endpoints cobrem a listagem de consolidados, a listagem paginada de registros, a criação individual e em lote (com deduplicação de NF-e), a atualização de valores em lote, a atualização individual e a exclusão de um registro.
Todos os endpoints exigem autenticação. Veja Autenticação para o fluxo de API Key. O Swagger oficial está em api.contabilidadealcance.com.br/docs.
Base path
/api/v1/sn-comercioEscopos necessários
sn_comercio:read- listagem de consolidados e de registrossn_comercio:write- criação individual e em lote, atualização de valores em lote, atualização individual e exclusão de registros
O escopo é derivado do prefixo público da rota: /sn-comercio vira o recurso sn_comercio (hífen → underscore), e o método HTTP define a ação (read para GET, write para POST/PUT/DELETE).
Ordem das rotas
As rotas literais POST /sn-comercio/registros/batch e PUT /sn-comercio/registros/batch-valores são declaradas antes da rota dinâmica PUT|DELETE /sn-comercio/registros/{registro_id} para que o FastAPI faça o match na ordem correta (batch/batch-valores não são interpretados como um registro_id).
Endpoints
GET /sn-comercio/consolidados
Lista os consolidados de comércio (total de faturamento por empresa e competência). Aceita filtro opcional por empresa_id. Lista vazia é um estado válido.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
empresa_id | int | query | não | Filtra os consolidados de uma empresa. |
Request
Sem corpo de requisição.
Response 200 OK
{
"status": "success",
"message": "Consolidados recuperados com sucesso",
"data": [
{
"id": 501,
"empresa_id": 10,
"competencia": "03/2026",
"total_faturamento": 45000.0,
"created_at": "2026-04-01T09:00:00",
"updated_at": "2026-04-05T11:20:00"
}
]
}Escopo: sn_comercio:read
GET /sn-comercio/registros
Lista os registros individuais de NF-e, com paginação. Aceita filtros opcionais por empresa e por intervalo de data/hora da nota.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
empresa_id | int | query | não | Filtra os registros de uma empresa. |
data_inicio | datetime | query | não | Filtro inicial de data_hora_nfe (ISO 8601). |
data_fim | datetime | query | não | Filtro final de data_hora_nfe (ISO 8601). |
limit | int | query | não | Itens por página. 1..10000. Default 1000. |
offset | int | query | não | Offset de paginação. >= 0. Default 0. |
Request
Sem corpo de requisição.
Response 200 OK
{
"status": "success",
"message": "Registros recuperados com sucesso",
"data": {
"items": [
{
"id": 9001,
"empresa_id": 10,
"consolidado_id": 501,
"data_hora_nfe": "2026-03-15T14:20:00",
"competencia": "03/2026",
"valor_produtos": 12000.0,
"numero_nfe": "1001",
"created_at": "2026-03-16T08:00:00",
"updated_at": "2026-03-16T08:00:00"
}
],
"total": 1
}
}O campo total reflete o total de registros que casam com o filtro, ignorando limit/offset.
Escopo: sn_comercio:read
POST /sn-comercio/registros
Cria um registro de comércio. Resolve (ou cria) o consolidado da (empresa_id, competencia) e recalcula o total automaticamente, em uma única transação.
Parâmetros
Este endpoint não recebe parâmetros de rota ou query. O corpo é um SnComercioRegistroCreate.
Request
{
"empresa_id": 10,
"data_hora_nfe": "2026-03-15T14:20:00",
"competencia": "03/2026",
"valor_produtos": 12000.0,
"numero_nfe": "1001"
}Response 201 Created
{
"status": "success",
"message": "Registro criado com sucesso",
"data": {
"id": 9001,
"empresa_id": 10,
"consolidado_id": 501,
"data_hora_nfe": "2026-03-15T14:20:00",
"competencia": "03/2026",
"valor_produtos": 12000.0,
"numero_nfe": "1001",
"created_at": "2026-03-16T08:00:00",
"updated_at": "2026-03-16T08:00:00"
}
}Erros de negócio respondem {"message": "<texto>"} com o código HTTP mapeado a partir da mensagem: 404 Not Found (não encontrado, ex.: empresa inexistente), 409 Conflict (já existe/duplicado) ou 422 Unprocessable Entity (demais casos).
Escopo: sn_comercio:write
POST /sn-comercio/registros/batch
Cria registros em lote (até 5000 itens), com deduplicação de NF-e: um item é considerado duplicata de um registro já gravado quando numero_nfe, competencia e empresa_id coincidem (numero_nfe nulo/vazio nunca é duplicata). Recalcula todos os consolidados afetados em uma única transação.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
em_duplicidade | string | query | não | Decisão para o lote inteiro quando há duplicatas: substituir (atualiza os existentes), duplicar (grava mesmo assim) ou ignorar (descarta os duplicados e grava o restante). Omitido = a API detecta e devolve 409 sem gravar nada. |
O corpo é uma lista de SnComercioRegistroCreate, com no máximo 5000 itens.
Request
[
{
"empresa_id": 10,
"data_hora_nfe": "2026-03-15T14:20:00",
"competencia": "03/2026",
"valor_produtos": 12000.0,
"numero_nfe": "1001"
}
]Response 201 Created
{
"status": "success",
"message": "Registros criados com sucesso",
"data": [
{
"id": 9001,
"empresa_id": 10,
"consolidado_id": 501,
"data_hora_nfe": "2026-03-15T14:20:00",
"competencia": "03/2026",
"valor_produtos": 12000.0,
"numero_nfe": "1001",
"created_at": "2026-03-16T08:00:00",
"updated_at": "2026-03-16T08:00:00"
}
]
}Response 409 Conflict (duplicatas encontradas e em_duplicidade não informado - nada é gravado)
{
"status": "pendente_decisao",
"message": "1 registro(s) do lote já existem para a mesma empresa, competência e número de NF-e.",
"data": {
"total_duplicatas": 1,
"decisoes_disponiveis": ["substituir", "duplicar", "ignorar"],
"duplicatas": [
{
"id": 9001,
"empresa_id": 10,
"competencia": "03/2026",
"numero_nfe": "1001",
"valor_atual": 12000.0,
"valor_novo": 13500.0,
"data_hora_nfe_atual": "2026-03-15T14:20:00",
"data_hora_nfe_novo": "2026-03-16T09:00:00"
}
]
}
}Reenvie o mesmo lote acrescentando ?em_duplicidade=substituir|duplicar|ignorar para resolver. Erros de validação de negócio (fora do fluxo de duplicidade) respondem {"message": "<texto>"} com 404, 409 ou 422, conforme a mensagem.
Escopo: sn_comercio:write
PUT /sn-comercio/registros/batch-valores
Atualiza valor e/ou número de NF-e de registros que já existem, identificados por id. Não faz deduplicação (só atualiza linhas existentes, nunca insere) e recalcula os consolidados afetados.
Parâmetros
Este endpoint não recebe parâmetros de rota ou query. O corpo é uma lista de SnComercioRegistroBatchValores, com no máximo 5000 itens.
Request
[{ "id": 9001, "valor_produtos": 13500.0, "numero_nfe": "1001" }]Response 200 OK
{
"status": "success",
"message": "Valores atualizados com sucesso",
"data": [
{
"id": 9001,
"empresa_id": 10,
"consolidado_id": 501,
"data_hora_nfe": "2026-03-15T14:20:00",
"competencia": "03/2026",
"valor_produtos": 13500.0,
"numero_nfe": "1001",
"created_at": "2026-03-16T08:00:00",
"updated_at": "2026-03-17T10:00:00"
}
]
}Se algum id do lote não existir, a chamada inteira é desfeita (rollback) e a API responde {"message": "Registro <id> não encontrado."} com 404 Not Found.
Escopo: sn_comercio:write
PUT /sn-comercio/registros/{registro_id}
Atualiza um registro individualmente (update parcial). Se empresa_id e/ou competencia mudarem, o registro é revinculado ao consolidado correto e ambos os consolidados (antigo e novo) são recalculados.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
registro_id | int | path | sim | ID do registro de NF-e. |
O corpo é um SnComercioRegistroUpdate.
Request
{ "valor_produtos": 14000.0 }Response 200 OK
{
"status": "success",
"message": "Registro atualizado com sucesso",
"data": {
"id": 9001,
"empresa_id": 10,
"consolidado_id": 501,
"data_hora_nfe": "2026-03-15T14:20:00",
"competencia": "03/2026",
"valor_produtos": 14000.0,
"numero_nfe": "1001",
"created_at": "2026-03-16T08:00:00",
"updated_at": "2026-03-17T15:30:00"
}
}Quando registro_id não existe, responde {"message": "Registro não encontrado."} com 404 Not Found.
Escopo: sn_comercio:write
DELETE /sn-comercio/registros/{registro_id}
Exclui um registro de NF-e e recalcula (ou apaga, se ficar vazio) o consolidado correspondente.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
registro_id | int | path | sim | ID do registro de NF-e. |
Request
Sem corpo de requisição.
Response 200 OK
{
"status": "success",
"message": "Registro removido com sucesso",
"data": null
}Quando registro_id não existe, responde {"message": "Registro não encontrado."} com 404 Not Found.
Escopo: sn_comercio:write
Schemas
SnComercioRegistroCreate
Corpo do POST /sn-comercio/registros e item do POST /sn-comercio/registros/batch.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
empresa_id | int | sim | ID da empresa (equivale ao customer.id). |
data_hora_nfe | datetime | sim | Data/hora de emissão da NF-e. |
competencia | string | sim | Formato MM/AAAA. |
valor_produtos | Decimal | não | >= 0, até 15 dígitos com 2 casas decimais. Default 0. |
numero_nfe | string | não | Máx. 50 caracteres. Chave da deduplicação no batch; null nunca é duplicata. |
SnComercioRegistroUpdate
Corpo do PUT /sn-comercio/registros/{registro_id}. Update parcial - todos os campos são opcionais, mas não aceitam null explícito (exceto numero_nfe, a única coluna anulável).
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
empresa_id | int | não | Alterar revincula o registro ao consolidado da nova empresa. |
data_hora_nfe | datetime | não | - |
competencia | string | não | Formato MM/AAAA. Alterar revincula o registro ao consolidado da nova competência. |
valor_produtos | Decimal | não | >= 0, até 15 dígitos com 2 casas decimais. |
numero_nfe | string | não | Máx. 50 caracteres. Aceita null explícito para limpar o campo. |
SnComercioRegistroBatchValores
Item do PUT /sn-comercio/registros/batch-valores.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
id | int | sim | ID do registro já gravado. |
valor_produtos | Decimal | sim | >= 0, até 15 dígitos com 2 casas decimais. |
numero_nfe | string | não | Máx. 50 caracteres. |
SnComercioDuplicataDetectada
Item de data.duplicatas na resposta 409 do POST /sn-comercio/registros/batch.
| Campo | Tipo | Observações |
|---|---|---|
id | int | ID do registro já gravado (candidato à substituição). |
empresa_id | int | - |
competencia | string | - |
numero_nfe | string | - |
valor_atual | float | valor_produtos já gravado. |
valor_novo | float | valor_produtos que está chegando no lote. |
data_hora_nfe_atual | datetime | - |
data_hora_nfe_novo | datetime | - |
SnComercioRegistroRead
Retorno de leitura de um registro. empresa_id, created_at e updated_at do JSON mapeiam as colunas id_cliente, data_hora_criacao e data_hora_atualizacao.
| Campo | Tipo | Observações |
|---|---|---|
id | int | - |
empresa_id | int | Coluna id_cliente no banco. |
consolidado_id | int | ID do consolidado ao qual o registro pertence. |
data_hora_nfe | datetime | - |
competencia | string | - |
valor_produtos | float | - |
numero_nfe | string | Pode ser null. |
created_at | datetime | Coluna data_hora_criacao. |
updated_at | datetime | Coluna data_hora_atualizacao. |
SnComercioConsolidadoRead
Retorno de leitura de um consolidado (somente leitura - os totais são calculados no servidor).
| Campo | Tipo | Observações |
|---|---|---|
id | int | - |
empresa_id | int | Coluna id_cliente no banco. |
competencia | string | Formato MM/AAAA. |
total_faturamento | float | Soma de valor_produtos dos registros da competência. |
created_at | datetime | Coluna data_hora_criacao. |
updated_at | datetime | Coluna data_hora_atualizacao. |
Notas
- Sucesso segue o envelope
{ status: "success", message, data }. Erros levantados comoHTTPException(404/409/422/500) respondem{ message }com o código HTTP correspondente. OPOST /sn-comercio/registros/batchtem um terceiro estado,{ status: "pendente_decisao", message, data }com409, específico para a deduplicação de NF-e. GET /sn-comercio/consolidadoseGET /sn-comercio/registrossempre retornam200 OK; lista vazia é estado normal antes da primeira importação.- Ordem de rotas (FastAPI):
POST /sn-comercio/registros/batchePUT /sn-comercio/registros/batch-valoressão declaradas antes dePUT|DELETE /sn-comercio/registros/{registro_id}. - Toda escrita em registros (criar, batch, batch-valores, atualizar, excluir) recalcula o(s) consolidado(s) da(s) competência(s) afetada(s) na mesma transação; um consolidado sem registros é apagado automaticamente.
- Duplicata de NF-e = mesmo
numero_nfena mesmacompetenciada mesmaempresa_id. Registro comnumero_nfenulo/vazio nunca é duplicata. A decisão deem_duplicidadevale para o lote inteiro, não item a item. POST /sn-comercio/registros/batchePUT /sn-comercio/registros/batch-valoresaceitam no máximo 5000 itens por chamada.