Contábil: REINF (EFD-Reinf)
Endpoints da WebApiAlcance para a EFD-Reinf, série R-4000 (pagamentos a beneficiário de lucros/dividendos e JCP). O domínio cobre o ciclo fiscal completo: transmitir lançamentos de lucro como eventos R-4010/R-4020/R-4040, fechar e reabrir o período (R-4099), retificar ou excluir (R-9000) um evento já aceito, registrar o fechamento feito por fora no portal e-CAC, consultar o estado do período e o histórico de cada lançamento, e gerenciar os lotes gerados (reenvio, reconsulta, arquivamento e download dos XMLs).
Todo envio à Receita é assíncrono: o endpoint cria o lote e o enfileira, e um worker interno faz o envio e o acompanhamento (polling) em segundo plano. O data das rotas de mutação é sempre o(s) lote(s) resultante(s) - use GET /reinf/lotes/{lote_id} ou GET /reinf/status para acompanhar o desfecho.
Todos os endpoints exigem autenticação. Veja Autenticação para o fluxo de API Key e JWT. O Swagger oficial está em api.contabilidadealcance.com.br/docs (tag Contabil: REINF (EFD-Reinf)).
Cinco rotas exigem sessão de usuário - API Key é recusada com 403
POST /reinf/eventos/{evento_id}/excluir, POST /reinf/periodos/marcar-fechamento-externo, POST /reinf/periodos/desmarcar-fechamento-externo, POST /reinf/lotes/{lote_id}/arquivar e POST /reinf/lotes/{lote_id}/desarquivar recusam credencial de API Key com 403 e a mensagem "<ação> não pode ser disparada por API Key — exige sessão de usuário (login).".
O motivo varia por rota (veja cada endpoint abaixo), mas em todas elas a operação registra a autoria de uma pessoa ou depende de confirmação feita na tela - o que uma integração server-to-server não tem como fornecer. As demais rotas do domínio, incluindo transmitir, fechar/reabrir período e retificar, aceitam API Key normalmente.
Base path
/api/v1/reinfEscopos necessários
reinf:read- todas as rotasGET(consultas de período, status, lotes, eventos, histórico e catálogos).reinf:write- todas as rotasPOST(transmitir, fechar/reabrir período, retificar, excluir, marcar/desmarcar fechamento externo, reenviar/consultar/arquivar/desarquivar lote).
O escopo é derivado do prefixo público da rota (/reinf vira o recurso reinf) e o método HTTP define a ação (read para GET, write para POST/PUT/PATCH/DELETE). Nenhuma rota do domínio exige perfil específico (administrador, gestor etc.) - qualquer usuário autenticado do escritório com o escopo correto pode operar a EFD-Reinf, inclusive perfis operacionais. O que algumas rotas exigem, além do escopo, é sessão de usuário (ver o aviso acima) - uma restrição de credencial, não de perfil.
Endpoints
Transmissão e fechamento de período
As três rotas a seguir são o fluxo fiscal principal: enviar os lançamentos de lucro, fechar o movimento do período e, se necessário, reabri-lo.
POST /reinf/transmitir
Transmite lançamentos de lucro à EFD-Reinf. Cria um ou mais lotes com os eventos R-4010 (beneficiário pessoa física), R-4020 (pessoa jurídica) ou R-4040 (beneficiário não identificado) - o tipo é decidido automaticamente pelo documento do sócio - e enfileira o envio assíncrono. Os lançamentos incluídos passam a Transmitido (somente leitura) até o desfecho.
O envio é dividido automaticamente em lotes de até 50 eventos cada.
Parâmetros
Sem parâmetros de rota ou query. O corpo é ReinfTransmissaoCreate.
Request
{
"id_cliente": 4521,
"per_apur": "2026-06",
"ids_lancamento_lucro": [8801, 8802, 8803]
}Response 201 Created
{
"status": "success",
"message": "Transmissão criada: 1 lote(s) enfileirado(s).",
"data": [
{
"id": 9012,
"id_cliente": 4521,
"id_usuario": 7,
"per_apur": "2026-06",
"ambiente": "producao",
"status": "pendente",
"nr_protocolo": null,
"tentativas_envio": 0,
"tentativas_polling": 0,
"enviado_em": null,
"processado_em": null,
"data_hora_criacao": "2026-08-17T09:00:00",
"total_eventos": 3,
"eventos_processados": 0,
"eventos_erro": 0,
"tipo_resumo": "Lucros",
"arquivado_em": null,
"id_usuario_arquivou": null,
"nome_usuario_arquivou": null,
"motivo_arquivamento": null
}
]
}data é sempre uma lista de ReinfLoteOut - um item por lote criado no split.
Erros: 404 cliente ou lançamento inexistente; 409 lançamento já transmitido ou já com evento REINF ativo; 422 lançamento cancelado, de outro cliente, com competência diferente do per_apur informado, ou marcado como fechado via e-CAC.
Escopo: reinf:write
POST /reinf/fechar-periodo
Envia o evento R-4099 de fechamento do período, em lote separado (regra do manual v2.7).
Parâmetros
Sem parâmetros de rota ou query. O corpo é ReinfFechamentoCreate.
Request
{
"id_cliente": 4521,
"per_apur": "2026-06"
}Response 201 Created
{
"status": "success",
"message": "Fechamento do período enfileirado.",
"data": {
"id": 9013,
"id_cliente": 4521,
"id_usuario": 7,
"per_apur": "2026-06",
"ambiente": "producao",
"status": "pendente",
"nr_protocolo": null,
"tentativas_envio": 0,
"tentativas_polling": 0,
"enviado_em": null,
"processado_em": null,
"data_hora_criacao": "2026-08-17T09:05:00",
"total_eventos": 1,
"eventos_processados": 0,
"eventos_erro": 0,
"tipo_resumo": "Fechamento",
"arquivado_em": null,
"id_usuario_arquivou": null,
"nome_usuario_arquivou": null,
"motivo_arquivamento": null
}
}data é um único ReinfLoteOut.
Erros: 409 existe evento R-4000 do período ainda sem recibo (a Receita exige o movimento completo antes de fechar); 422 não há evento algum no período.
Escopo: reinf:write
POST /reinf/periodos/reabrir
Envia o R-4099 de reabertura (fechRet=1) em lote próprio. É pré-requisito para retificar ou excluir um evento de período já fechado.
Reabrir não refecha sozinho
Depois da reabertura, o movimento fica ABERTO na Receita até o refechamento explícito via POST /reinf/fechar-periodo. Não existe automação da sequência reabrir → corrigir → refechar - cabe a quem opera concluir o ciclo. Use GET /reinf/periodos/reabertos para acompanhar períodos abertos por reabertura e ainda não refechados.
Parâmetros
Sem parâmetros de rota ou query. O corpo é ReinfReaberturaCreate (mesmos campos do fechamento).
Request
{
"id_cliente": 4521,
"per_apur": "2026-06"
}Response 201 Created
{
"status": "success",
"message": "Reabertura do período enfileirada.",
"data": {
"id": 9014,
"id_cliente": 4521,
"id_usuario": 7,
"per_apur": "2026-06",
"ambiente": "producao",
"status": "pendente",
"total_eventos": 1,
"eventos_processados": 0,
"eventos_erro": 0,
"tipo_resumo": "Reabertura",
"data_hora_criacao": "2026-08-17T10:00:00"
}
}data é um único ReinfLoteOut (resposta resumida acima - os demais campos seguem o mesmo formato do fechamento).
Erros: 409 o período já está ABERTO (nada a reabrir) ou a situação já é INDETERMINADA (existe R-4099 sem desfecho conhecido - inclusive guard de duplo clique); 404 cliente inexistente; 422 cliente sem CNPJ válido.
Escopo: reinf:write
Retificação de evento (fluxo em 3 passos)
Retificar um evento já aceito pela Receita não é um clique só. O fluxo exige destravar os lançamentos, corrigi-los pelas rotas normais de lançamento de lucro e só então confirmar a retificação - o objetivo é impedir que a retificação nº 1 envie exatamente o mesmo dado do evento original.
POST /reinf/eventos/{evento_id}/iniciar-retificacao- destrava os lançamentos para edição;- o usuário corrige os lançamentos pelas rotas do domínio de lançamento de lucro (fora deste documento);
POST /reinf/eventos/{evento_id}/retificar- congela o dado já editado, cria o lote e transmite. OuPOST /reinf/eventos/{evento_id}/cancelar-retificacaopara desistir sem transmitir nada.
Enquanto os lançamentos estiverem "Em retificação", eles não podem ser transmitidos (POST /reinf/transmitir recusa com 409) nem excluídos.
POST /reinf/eventos/{evento_id}/iniciar-retificacao
Passo 1 de 3. Marca os lançamentos do evento alvo como "Em retificação" (editáveis) e os devolve, para a tela de edição. Nenhum lote é criado e nada é enviado à Receita.
É idempotente: chamar de novo devolve o estado atual com ja_estava_em_retificacao: true.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
evento_id | int | path | sim | ID do evento REINF a corrigir |
Sem corpo de requisição.
Response 200 OK
{
"status": "success",
"message": "Retificação iniciada: lançamentos liberados para edição.",
"data": {
"id_evento": 5501,
"id_cliente": 4521,
"per_apur": "2026-06",
"tipo_evento": "R4010",
"nr_recibo": "1.2.0000000000000000123",
"status_lancamentos": "Em retificação",
"ja_estava_em_retificacao": false,
"lancamentos": [
{
"id": 8801,
"id_cliente": 4521,
"id_qsa_cliente": 301,
"competencia": "06/2026",
"natureza_rendimento": "12001",
"valor_liquido": "3500.00",
"status": "Em retificação"
}
]
}
}data é ReinfRetificacaoAbertaOut.
Erros: 404 evento inexistente; 409 alvo sem recibo, alvo já retificado/excluído, tipo não corrigível (R-4099/R-9000), período FECHADO (reabra antes) ou INDETERMINADO, correção do mesmo alvo já em andamento, e evento sem lançamento vinculado.
Escopo: reinf:write
POST /reinf/eventos/{evento_id}/cancelar-retificacao
Passo 3 alternativo. Devolve os lançamentos do evento a Transmitido (somente leitura) sem transmitir nada - o oposto do passo 1. As edições já salvas nos lançamentos não são revertidas: o cancelamento devolve a trava, não o conteúdo anterior.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
evento_id | int | path | sim | ID do evento REINF em retificação |
Sem corpo de requisição.
Response 200 OK
{
"status": "success",
"message": "Retificação cancelada: lançamentos retravados, nada foi transmitido.",
"data": {
"id_evento": 5501,
"id_cliente": 4521,
"per_apur": "2026-06",
"tipo_evento": "R4010",
"nr_recibo": "1.2.0000000000000000123",
"status_lancamentos": "Transmitido",
"ja_estava_em_retificacao": false,
"lancamentos": [
{
"id": 8801,
"id_cliente": 4521,
"id_qsa_cliente": 301,
"competencia": "06/2026",
"natureza_rendimento": "12001",
"valor_liquido": "3500.00",
"status": "Transmitido"
}
]
}
}data é ReinfRetificacaoAbertaOut.
Erros: 404 evento inexistente; 409 a retificação já foi transmitida (existe correção em andamento - nada a cancelar) ou nenhum lançamento do evento está "Em retificação".
Escopo: reinf:write
POST /reinf/eventos/{evento_id}/retificar
Passo 2 de 3. Cria um lote próprio com o evento retificador (mesmo tipo do alvo, indRetif=2 e o nrRecibo do alvo, congelado no momento deste request).
Efeito fiscal irreversível após o aceite da Receita
O evento original não é apagado: ele passa a retificado somente depois que a Receita devolve o recibo do retificador. Não há como desfazer pelo produto depois do aceite - a retificação é uma correção fiscal, não um cancelamento.
Exige que o passo 1 tenha sido chamado e que os lançamentos estejam "Em retificação" - caso contrário a rota responde 409. É essa exigência que garante que o dado transmitido passou por revisão consciente. Ao criar o lote, os lançamentos voltam a Transmitido (somente leitura) enquanto o evento está em voo.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
evento_id | int | path | sim | ID do evento REINF a retificar (passo 1 já concluído) |
Sem corpo de requisição.
Response 201 Created
{
"status": "success",
"message": "Retificação enfileirada.",
"data": {
"id": 9015,
"id_cliente": 4521,
"per_apur": "2026-06",
"status": "pendente",
"total_eventos": 1,
"eventos_processados": 0,
"eventos_erro": 0,
"tipo_resumo": "Lucros",
"data_hora_criacao": "2026-08-17T11:00:00"
}
}data é um único ReinfLoteOut.
Erros: 404 evento inexistente; 409 lançamentos não destravados (chame iniciar-retificacao antes), alvo sem recibo, alvo já retificado/excluído, alvo de tipo não corrigível (R-4099/R-9000), período FECHADO (reabra antes - o sistema não reabre sozinho) ou INDETERMINADO, e correção do mesmo alvo já em andamento (idempotência).
Escopo: reinf:write
Exclusão de evento (R-9000)
POST /reinf/eventos/{evento_id}/excluir
Cria um lote próprio com o evento R-9000 (evtExclusao) do evento alvo.
Destrutivo: derruba a tempestividade do evento original
A exclusão não é "desfazer": a Receita perde o registro do evento e os efeitos jurídicos de tempestividade são perdidos (exposição a multa). Depois dela, o rendimento precisa ser reenviado como evento original. Quando a exclusão é aceita, o lançamento correspondente volta a processado para permitir esse reenvio.
Esta rota exige sessão de usuário - uma API Key recebe 403. É a única mutação do domínio com essa restrição de credencial: a confirmação por digitação na tela é a última barreira antes de perder a tempestividade, e uma integração não a executa.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
evento_id | int | path | sim | ID do evento REINF a excluir |
O corpo é ReinfExclusaoCreate.
Request
{
"motivo": "Sócio errado no lançamento - será reenviado como evento original"
}Response 201 Created
{
"status": "success",
"message": "Exclusão (R-9000) enfileirada.",
"data": {
"id": 9016,
"id_cliente": 4521,
"per_apur": "2026-06",
"status": "pendente",
"total_eventos": 1,
"eventos_processados": 0,
"eventos_erro": 0,
"tipo_resumo": "Exclusão",
"data_hora_criacao": "2026-08-17T11:30:00"
}
}data é um único ReinfLoteOut.
motivo é obrigatório e fica persistido para auditoria da decisão.
Erros: 403 credencial de API Key; 404 evento inexistente; 422 motivo ausente ou vazio; 409 os mesmos guards da retificação (recibo, alvo já corrigido, tipo, período, operação em voo).
Escopo: reinf:write + sessão de usuário (API Key recusada)
Consulta e fechamento de período
GET /reinf/periodos/reabertos
Lista todos os pares (cliente, período) cujo último R-4099 aceito é uma reabertura - ou seja, o movimento está aberto na Receita por intervenção e aguarda refechamento. É o indicador global: não recebe parâmetro de propósito.
Parâmetros
Nenhum.
Response 200 OK
{
"status": "success",
"message": "Períodos reabertos recuperados com sucesso!",
"data": [
{
"id_cliente": 4521,
"nome_cliente": "ACME SERVICOS LTDA",
"per_apur": "2026-05",
"reaberto_em": "2026-08-10T14:20:00",
"dias_reaberto": 7,
"id_lote_reabertura": 8990
}
]
}data é um array de ReinfPeriodoReabertoOut.
Escopo: reinf:read
GET /reinf/periodos/estado
Estado ternário do movimento do período (aberto | fechado | indeterminado), derivado dos R-4099 do período, com as evidências que sustentam a resposta.
Parâmetros de query
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id_cliente | int | sim | ID do cliente (customer.id). |
per_apur | str | sim | Período de apuração 'YYYY-MM'. |
Request
GET /api/v1/reinf/periodos/estado?id_cliente=4521&per_apur=2026-06Response 200 OK
{
"status": "success",
"message": "Estado do período recuperado com sucesso!",
"data": {
"id_cliente": 4521,
"per_apur": "2026-06",
"estado": "fechado",
"ultimo_fechamento": {
"id_evento": 5510,
"id_lote": 9013,
"fech_ret": 0,
"nr_recibo": "1.2.0000000000000000456",
"processado_em": "2026-08-17T09:10:00"
},
"r4099_em_transito": null,
"fechado_externamente": false,
"fechamento_externo": null,
"reaberto_em": null,
"dias_reaberto": null,
"pode_fechar": false,
"motivo": "Período já está fechado."
}
}data é ReinfEstadoPeriodoOut. indeterminado significa que existe um R-4099 sem desfecho conhecido; enquanto isso, fechar-periodo, reabrir, retificar e excluir recusam todos os eventos daquela competência (fail-closed).
Escopo: reinf:read
GET /reinf/periodos/estado-competencia
Situação (aberto | fechado | indeterminado) de todos os clientes elegíveis (matriz PJ, ativa, com sócio) numa competência, numa única resposta - substitui varrer GET /reinf/periodos/estado cliente a cliente. É a fonte da tela de fechamento em lote.
Parâmetros de query
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
per_apur | str | sim | Período de apuração 'YYYY-MM'. |
Request
GET /api/v1/reinf/periodos/estado-competencia?per_apur=2026-06Response 200 OK
{
"status": "success",
"message": "Estado da competência recuperado com sucesso!",
"data": {
"per_apur": "2026-06",
"abertos": 12,
"fechados": 34,
"em_transito": 1,
"reabertos": 2,
"clientes": [
{
"id_cliente": 4521,
"nome_cliente": "ACME SERVICOS LTDA",
"estado": "fechado",
"reaberto": false,
"reaberto_em": null,
"dias_reaberto": null,
"pode_fechar": false,
"motivo": "Período já está fechado.",
"nr_recibo_ultimo_r4099": "1.2.0000000000000000456",
"fechado_externamente": false,
"id_lote_em_transito": null,
"total_lancamentos": 3,
"lancamentos_nao_transmitidos": 0
}
]
}
}data é ReinfEstadoCompetenciaOut. 422 se per_apur estiver malformado.
Escopo: reinf:read
GET /reinf/periodos/fechamentos
Histórico de fechamentos (cross-competência), com filtros e paginação - uma linha por par (cliente, competência) efetivamente fechado. Um período fechado e depois reaberto continua listado, com reaberto: true.
Parâmetros de query
| Parâmetro | Tipo | Default | Descrição |
|---|---|---|---|
per_apur | str | - | Filtrar por competência 'YYYY-MM'. Omitido = todas. |
id_cliente | int | - | Filtrar por cliente. Omitido = todos. |
page | int | 1 | Página (1-based, ≥ 1). |
per_page | int | 25 | Itens por página (1-200). |
Request
GET /api/v1/reinf/periodos/fechamentos?per_apur=2026-06&page=1&per_page=25Response 200 OK
{
"status": "success",
"message": "Histórico de fechamentos recuperado com sucesso!",
"data": {
"total": 1,
"page": 1,
"per_page": 25,
"itens": [
{
"id_cliente": 4521,
"razao_social": "ACME SERVICOS LTDA",
"cnpj": "12345678000199",
"per_apur": "2026-06",
"nr_recibo": "1.2.0000000000000000456",
"fechado_em": "2026-08-17T09:10:00",
"fechado_por": "Maria Silva",
"origem": "sistema",
"reaberto": false
}
]
}
}data é ReinfFechamentosPaginadosOut - envelope total/page/per_page/itens, diferente do envelope items/total_pages/current_page usado na listagem de lotes. origem distingue o fechamento feito pelo sistema (sistema, R-4099 com recibo da RFB) do marcado como feito no e-CAC (externo). 422 se per_apur for informado malformado.
Escopo: reinf:read
POST /reinf/periodos/marcar-fechamento-externo
Registra que o R-4099 de fechamento desta competência foi transmitido no portal e-CAC, por fora deste sistema.
É uma afirmação, não um fato observado - nada é enviado à Receita
Esta rota não cria nenhum evento e não fala com a Receita. Ela apenas registra a afirmação de uma pessoa de que o fechamento já aconteceu por fora, para que o estado derivado do período deixe de ficar aberto indefinidamente (o que travaria o arquivamento de lotes obsoletos).
A marcação nunca sobrescreve prova produzida pelo próprio sistema: um R-4099 em voo continua deixando o período indeterminado, e um R-4099 nosso aceito continua mandando. A marcação só preenche o vazio quando não existe nenhum R-4099 nosso. Reabrir o período pelo app depois disso é permitido e supera a marcação naturalmente.
Exige sessão de usuário - API Key recebe 403.
Parâmetros
Sem parâmetros de rota ou query. O corpo é ReinfFechamentoExternoCreate.
Request
{
"id_cliente": 4521,
"per_apur": "2026-06",
"motivo": "Cliente transmitiu e fechou a competência direto no e-CAC",
"nr_recibo_ecac": "1.2.0000000000000000123"
}Response 200 OK
{
"status": "success",
"message": "Competência marcada como fechada no e-CAC (nada foi enviado à Receita).",
"data": {
"id_cliente": 4521,
"per_apur": "2026-06",
"estado": "fechado",
"ultimo_fechamento": null,
"r4099_em_transito": null,
"fechado_externamente": true,
"fechamento_externo": {
"id_cliente": 4521,
"per_apur": "2026-06",
"nr_recibo_ecac": "1.2.0000000000000000123",
"motivo": "Cliente transmitiu e fechou a competência direto no e-CAC",
"id_usuario_marcou": 7,
"nome_usuario_marcou": "Maria Silva",
"marcado_em": "2026-08-17T12:00:00"
},
"reaberto_em": null,
"dias_reaberto": null,
"pode_fechar": false,
"motivo": "Período marcado como fechado no e-CAC."
}
}data é o ReinfEstadoPeriodoOut resultante. motivo é obrigatório (máx. 500 caracteres); nr_recibo_ecac é opcional (máx. 52 caracteres) - quando informado, é o recibo emitido pela RFB para a pessoa que fechou pelo e-CAC. A operação é idempotente: marcar de novo devolve o estado atual sem reescrever autor, carimbo ou motivo.
Erros: 403 credencial de API Key; 404 cliente inexistente; 422 per_apur malformado, motivo vazio ou cliente sem CNPJ válido.
Escopo: reinf:write + sessão de usuário (API Key recusada)
POST /reinf/periodos/desmarcar-fechamento-externo
Retira a marcação de fechamento externo (e-CAC) da competência. Sempre permitido - não há guard de estado, pelo mesmo motivo do desarquivamento de lote: uma marcação errada (competência ou cliente trocado) não pode ficar irrecuperável.
Parâmetros
Sem parâmetros de rota ou query. O corpo é ReinfFechamentoExternoRemove - apenas id_cliente e per_apur.
Request
{
"id_cliente": 4521,
"per_apur": "2026-06"
}Response 200 OK
{
"status": "success",
"message": "Marcação de fechamento externo retirada.",
"data": {
"id_cliente": 4521,
"per_apur": "2026-06",
"estado": "aberto",
"ultimo_fechamento": null,
"r4099_em_transito": null,
"fechado_externamente": false,
"fechamento_externo": null,
"reaberto_em": null,
"dias_reaberto": null,
"pode_fechar": true,
"motivo": null
}
}data é o ReinfEstadoPeriodoOut resultante. Idempotente: se não havia marcação, a chamada é um no-op.
Erros: 403 credencial de API Key; 404 cliente inexistente; 422 per_apur malformado ou cliente sem CNPJ válido.
Escopo: reinf:write + sessão de usuário (API Key recusada)
Catálogos e status
GET /reinf/naturezas
Catálogo canônico de naturezas de rendimento (Tabela 01 do EFD-Reinf) aplicáveis a lucros - alimenta o select do lançamento no front.
Parâmetros
Nenhum.
Response 200 OK
{
"status": "success",
"message": "Naturezas recuperadas com sucesso!",
"data": [
{ "codigo": "12001", "descricao": "Lucros e dividendos" },
{ "codigo": "12002", "descricao": "Juros sobre o capital próprio (JCP)" },
{ "codigo": "12003", "descricao": "Rendimentos de partes beneficiárias ou de fundador" }
]
}Escopo: reinf:read
GET /reinf/status
Resumo da situação REINF de um cliente em um período: contagem de lotes e eventos por desfecho, se o período está fechado e por qual via.
Parâmetros de query
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id_cliente | int | sim | ID do cliente (customer.id). |
per_apur | str | sim | Período de apuração 'YYYY-MM'. |
Request
GET /api/v1/reinf/status?id_cliente=4521&per_apur=2026-06Response 200 OK
{
"status": "success",
"message": "Status REINF recuperado com sucesso!",
"data": {
"id_cliente": 4521,
"per_apur": "2026-06",
"total_lotes": 2,
"total_eventos": 4,
"eventos_pendentes": 0,
"eventos_enviados": 0,
"eventos_processados": 4,
"eventos_erro": 0,
"periodo_fechado": true,
"fechado_externamente": false,
"lotes": [
{
"id": 9012,
"id_cliente": 4521,
"per_apur": "2026-06",
"status": "processado",
"total_eventos": 3,
"eventos_processados": 3,
"eventos_erro": 0,
"tipo_resumo": "Lucros"
}
]
}
}data é ReinfStatusOut. periodo_fechado: true com fechado_externamente: true significa fechado no e-CAC por fora - não existe R-4099 nosso nem recibo neste sistema para esse caso.
Escopo: reinf:read
Lotes e eventos
GET /reinf/lotes
Lista lotes REINF com filtros e paginação. Alimenta tanto a listagem geral quanto a tela de correções (é nela que se age sobre um lote em erro).
Parâmetros de query
| Parâmetro | Tipo | Default | Descrição |
|---|---|---|---|
id_cliente | int | - | Filtra por cliente. |
per_apur | str | - | Filtra por período 'YYYY-MM'. |
status | str | - | Filtra pelo status do lote: pendente, enviando, aguardando_processamento, processado, processado_com_erros, erro_envio. |
visibilidade | relevantes | todos | todos | todos devolve tudo; relevantes esconde lotes arquivados à mão e os auto-mortos (todos os eventos retificados/excluídos) - a contagem escondida volta em ocultos. |
sort_by | data_hora_criacao | per_apur | status | data_hora_criacao | Coluna de ordenação (whitelist). |
sort_dir | asc | desc | desc | Direção da ordenação. |
page | int (≥ 1) | 1 | Página (1-based). |
per_page | int (1-500) | - | Itens por página. Se omitido, retorna todos. |
Request
GET /api/v1/reinf/lotes?id_cliente=4521&per_apur=2026-06&page=1&per_page=25Response 200 OK
{
"status": "success",
"message": "Lotes recuperados com sucesso!",
"data": {
"items": [
{
"id": 9012,
"id_cliente": 4521,
"id_usuario": 7,
"per_apur": "2026-06",
"ambiente": "producao",
"status": "processado",
"nr_protocolo": "1.2.99999999999999999999",
"tentativas_envio": 1,
"tentativas_polling": 2,
"enviado_em": "2026-08-17T09:01:10",
"processado_em": "2026-08-17T09:03:40",
"data_hora_criacao": "2026-08-17T09:00:00",
"total_eventos": 3,
"eventos_processados": 3,
"eventos_erro": 0,
"tipo_resumo": "Lucros",
"arquivado_em": null,
"id_usuario_arquivou": null,
"nome_usuario_arquivou": null,
"motivo_arquivamento": null
}
],
"total": 1,
"total_pages": 1,
"current_page": 1,
"per_page": 25,
"ocultos": 0
}
}data é PaginatedReinfLotes. Os XMLs não são retornados aqui - use GET /reinf/lotes/{lote_id}/xmls. visibilidade=todos é o default de propósito: a tela de correções compartilha esta mesma listagem e precisa enxergar exatamente os lotes com problema.
Escopo: reinf:read
GET /reinf/eventos/por-lancamento
Rota deprecada - use GET /reinf/lancamentos/historico
Marcada deprecated: true no OpenAPI. Devolve só o evento vivo de cada lançamento (sem histórico de retificações), o que faz a UI exibir o valor atual do lançamento como se fosse o valor declarado. GET /reinf/lancamentos/historico a sucede com o contrato correto - não construa nada novo sobre esta rota.
Parâmetros de query
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
ids_lancamento | list[int] | sim | IDs de lancamento_lucro (repita o parâmetro). Máx. 200 por chamada. |
Request
GET /api/v1/reinf/eventos/por-lancamento?ids_lancamento=8801&ids_lancamento=8802Response 200 OK
{
"status": "success",
"message": "Eventos recuperados com sucesso!",
"data": [
{
"id_lancamento_lucro": 8801,
"per_apur": "2026-06",
"evento": {
"id": 5501,
"id_lote": 9012,
"id_cliente": 4521,
"id_lancamento_lucro": 8801,
"tipo_evento": "R4010",
"id_evento_reinf": null,
"status": "processado",
"fech_ret": null,
"id_evento_retificado": null,
"nr_recibo": "1.2.0000000000000000123",
"hash_evento": "a1b2c3d4",
"codigo_erro": null,
"descricao_erro": null,
"situacao_receita": null,
"data_hora_criacao": "2026-08-17T09:00:00",
"atualizado_em": "2026-08-17T09:03:40"
}
}
]
}data é um array de ReinfEventoDoLancamentoOut - só entram lançamentos com evento vivo. Não retorna XML - o XML tem CPF/CNPJ do beneficiário e continua restrito a GET /reinf/lotes/{lote_id}/eventos/{evento_id}.
Escopo: reinf:read
GET /reinf/lancamentos/historico
Sucede GET /reinf/eventos/por-lancamento. Para cada lançamento pedido, devolve a cadeia completa do que já foi declarado à Receita (do mais antigo ao mais recente) e o evento vivo que habilita "Retificar"/"Excluir" na tela.
Parâmetros de query
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
ids_lancamento | list[int] | sim | IDs de lancamento_lucro (repita o parâmetro). Máx. 200 por chamada. |
Request
GET /api/v1/reinf/lancamentos/historico?ids_lancamento=8801&ids_lancamento=8802Response 200 OK
{
"status": "success",
"message": "Histórico recuperado com sucesso!",
"data": [
{
"id_lancamento_lucro": 8801,
"marcacao": "original",
"evento_vivo": {
"id_lancamento_lucro": 8801,
"per_apur": "2026-06",
"evento": {
"id": 5501,
"id_lote": 9012,
"id_cliente": 4521,
"tipo_evento": "R4010",
"status": "processado",
"nr_recibo": "1.2.0000000000000000123"
}
},
"historico": [
{
"id_evento": 5501,
"ordem": 1,
"marcacao": "original",
"per_apur": "2026-06",
"nr_recibo": "1.2.0000000000000000123",
"status_evento": "processado",
"transmitido_em": "2026-08-17T09:03:40",
"snapshot_disponivel": true,
"congelado_em": "2026-08-17T09:00:00",
"competencia": "06/2026",
"data_pagamento": "2026-06-30",
"natureza_rendimento": "12001",
"valor_bruto": "3500.00",
"valor_liquido": "3500.00",
"valor_ir_retido": "0.00",
"valor_ata_utilizada": null,
"valor_base_ir": null
}
]
}
]
}data é um array de ReinfHistoricoDoLancamentoOut. Todo id_lancamento pedido entra na resposta, mesmo sem nenhum evento (marcacao: "nao_transmitido", historico: []). snapshot_disponivel: false (vínculo anterior ao congelamento do snapshot) devolve os valores nulos - nunca um número sem lastro. Não retorna XML.
Escopo: reinf:read
GET /reinf/lancamentos-saude/declarados
Diz, para cada lançamento de plano de saúde informado, se ele já foi declarado - o plano de saúde não transmite sozinho: os lançamentos não cancelados do sócio viajam junto no mesmo R-4010 do lucro dele.
Parâmetros de query
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
ids_lancamento | list[int] | sim | IDs de lancamento_plano_saude (repita o parâmetro). Máx. 200 por chamada. |
Request
GET /api/v1/reinf/lancamentos-saude/declarados?ids_lancamento=4401Response 200 OK
{
"status": "success",
"message": "Lançamentos de plano de saúde declarados recuperados com sucesso!",
"data": [
{
"id_lancamento": 4401,
"id_evento": 5501,
"status_evento": "processado",
"nr_recibo": "1.2.0000000000000000123"
}
]
}data é um array de ReinfLancamentoSaudeDeclaradoOut - só aparece quem tem vínculo ativo (pendente, enviado ou processado); ausência do ID na resposta é "nada a exibir". Não confundir os IDs desta rota (lancamento_plano_saude) com os de GET /reinf/lancamentos/historico (lancamento_lucro) - são tabelas diferentes.
Escopo: reinf:read
GET /reinf/lotes/{lote_id}
Detalhe de um lote, com a lista de eventos que ele contém (sem XML).
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
lote_id | int | path | sim | ID do lote REINF |
Response 200 OK
{
"status": "success",
"message": "Lote recuperado com sucesso!",
"data": {
"id": 9012,
"id_cliente": 4521,
"per_apur": "2026-06",
"ambiente": "producao",
"status": "processado",
"nr_protocolo": "1.2.99999999999999999999",
"total_eventos": 1,
"eventos_processados": 1,
"eventos_erro": 0,
"tipo_resumo": "Lucros",
"eventos": [
{
"id": 5501,
"id_lote": 9012,
"id_cliente": 4521,
"id_lancamento_lucro": 8801,
"tipo_evento": "R4010",
"status": "processado",
"nr_recibo": "1.2.0000000000000000123",
"codigo_erro": null,
"descricao_erro": null
}
],
"ocorrencias": []
}
}data é ReinfLoteDetailOut. ocorrencias são as recusas de nível lote devolvidas pela Receita (não têm correspondência 1:1 com um evento específico) e refletem sempre a última resposta conhecida. 404 quando o lote não existe.
Escopo: reinf:read
GET /reinf/lotes/{lote_id}/lancamentos
O que foi declarado em cada evento do lote - sócio, competência, valores. Complementa GET /reinf/lotes/{lote_id}, que informa o desfecho de cada evento mas não o conteúdo.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
lote_id | int | path | sim | ID do lote REINF |
Response 200 OK
{
"status": "success",
"message": "Lançamentos recuperados com sucesso!",
"data": [
{
"id_evento": 5501,
"id": 8801,
"id_qsa_cliente": 301,
"nome_socio": "João da Silva",
"competencia": "06/2026",
"data_pagamento": "2026-06-30",
"data_registro": "2026-06-28",
"natureza_rendimento": "12001",
"valor_liquido": "3500.00",
"valor_bruto": "3500.00",
"valor_ata_utilizada": null,
"valor_ir_retido": "0.00",
"status": "Transmitido",
"snapshot_disponivel": true,
"origem": "lucro",
"operadora_nome": null,
"nome_dependente": null,
"valor_saude": null
}
]
}data é um array de ReinfLancamentoDoEventoOut - vale tanto para envio individual quanto em lote, e um evento pode agrupar N lançamentos do mesmo beneficiário. origem discrimina linhas de lucro ("lucro") das de plano de saúde que viajaram de carona ("plano_saude"); os campos exclusivos de cada eixo ficam null no outro. Lista vazia é resposta legítima (lote só de R-4099 não declara lançamento). 404 apenas quando o lote não existe.
Escopo: reinf:read
GET /reinf/lotes/{lote_id}/xmls
Baixa um .zip com o XML assinado de cada evento do lote e a resposta crua da Receita (quando já respondida).
O conteúdo contém CPF/CNPJ e valores do beneficiário
O pacote leva o XML declarado à Receita, com os dados pessoais do sócio/beneficiário. Trate a resposta como dado sensível ao consumir esta rota.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
lote_id | int | path | sim | ID do lote REINF |
Response 200 OK
Corpo binário application/zip (não segue o envelope JSON padrão), com o cabeçalho Content-Disposition: attachment; filename="...". Conteúdo: evento-<id>-envio.xml para cada evento com XML gerado, e lote-<id>-resposta.xml quando a Receita já respondeu. Não existe "XML de recibo por evento": a RFB devolve uma resposta por lote, e por evento o banco guarda apenas o número do recibo.
Erros: 409 quando não há nada a empacotar ainda (lote pendente, XMLs não montados).
Escopo: reinf:read
POST /reinf/lotes/{lote_id}/reenviar
Reenvia um lote que ficou em erro_envio ou processado_com_erros. Fora desses dois status, a rota recusa com 409.
regenerar_xml=true pode duplicar a declaração
O padrão (regenerar_xml=false) preserva o mesmo Id/XML gravados - a regra de duplicidade da Receita (MS0022) devolve o recibo original sem criar nada novo. Use regenerar_xml=true somente quando o operador confirmou na Receita que o evento foi rejeitado (não existe recibo para ele); do contrário o mesmo rendimento é declarado duas vezes, porque esta rota não faz retificação. Eventos com recibo já gravado continuam intocados mesmo com regenerar_xml=true.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
lote_id | int | path | sim | ID do lote REINF |
regenerar_xml | bool | query | não | Default false. true gera novo Id/XML - use só com rejeição confirmada na Receita. |
Sem corpo de requisição.
Response 200 OK
{
"status": "success",
"message": "Lote reenfileirado para transmissão.",
"data": {
"id": 9012,
"id_cliente": 4521,
"per_apur": "2026-06",
"status": "pendente",
"tentativas_envio": 2,
"total_eventos": 3,
"eventos_processados": 0,
"eventos_erro": 0
}
}data é ReinfLoteOut.
Erros: 404 lote inexistente; 409 lote fora de erro_envio/processado_com_erros, ou lote com lançamento marcado como "Via e-CAC" (não pode ser reenviado por esta via).
Escopo: reinf:write
POST /reinf/lotes/{lote_id}/consultar
Reenfileira a consulta do lote na Receita, sem reenviar nada. Serve para os casos em que o polling automático esgotou as tentativas ou foi perdido (reinício do worker no meio do intervalo) e o lote ficou preso em aguardando_processamento de propósito - marcá-lo como erro levaria a um reenvio que duplicaria a declaração.
Enquanto o lote não tem desfecho, o período do cliente fica indeterminado e fechar/reabrir/retificar/excluir recusam todos os eventos daquela competência - esta rota é a saída.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
lote_id | int | path | sim | ID do lote REINF |
Sem corpo de requisição. Cada chamada vale uma consulta - se a Receita responder que o lote ainda está em processamento, chame de novo mais tarde.
Response 200 OK
{
"status": "success",
"message": "Consulta do lote reenfileirada.",
"data": {
"id": 9012,
"id_cliente": 4521,
"per_apur": "2026-06",
"status": "aguardando_processamento",
"tentativas_polling": 6,
"nr_protocolo": "1.2.99999999999999999999"
}
}data é ReinfLoteOut.
Erros: 404 lote inexistente; 409 lote fora de aguardando_processamento (a mensagem informa o status atual - nos demais casos o desfecho já é conhecido); 409 lote sem número de protocolo (sem protocolo não há o que consultar).
Escopo: reinf:write
POST /reinf/lotes/{lote_id}/arquivar
Tira o lote da listagem quando consultada com visibilidade=relevantes. Nada é apagado e nada é enviado à Receita - o lote continua íntegro em GET /reinf/lotes?visibilidade=todos, no detalhe, no .zip de XMLs e em todos os guards fiscais do domínio. Não existe (e não vai existir) exclusão de lote.
Exige sessão de usuário: a operação grava autoria (quem arquivou), e uma API Key não corresponde a um usuário.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
lote_id | int | path | sim | ID do lote REINF |
O corpo é opcional - ReinfArquivamentoCreate.
Request
{
"motivo": "Lote de teste do ambiente restrito"
}Response 200 OK
{
"status": "success",
"message": "Lote arquivado (segue íntegro e consultável).",
"data": {
"id": 9012,
"id_cliente": 4521,
"per_apur": "2026-06",
"status": "processado",
"arquivado_em": "2026-08-17T13:00:00",
"id_usuario_arquivou": 7,
"nome_usuario_arquivou": "Maria Silva",
"motivo_arquivamento": "Lote de teste do ambiente restrito"
}
}data é ReinfLoteOut. motivo é opcional (máx. 500 caracteres). Idempotente: arquivar de novo devolve o estado atual sem reescrever autor ou motivo. Reversível a qualquer momento por POST /reinf/lotes/{lote_id}/desarquivar.
Erros: 403 credencial de API Key; 404 lote inexistente; 409 lote em voo (pendente/enviando/aguardando_processamento), evento sem desfecho (pendente/enviado), ou lote que ainda trava o fechamento do período (evento R-4000 sem recibo com o período ainda não fechado).
Escopo: reinf:write + sessão de usuário (API Key recusada)
POST /reinf/lotes/{lote_id}/desarquivar
Devolve o lote à listagem padrão. Sempre permitido - não há guard de estado, simétrico ao arquivamento por decisão de produto: arquivamento sem volta deixaria lotes fora de vista para sempre.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
lote_id | int | path | sim | ID do lote REINF |
Sem corpo de requisição.
Response 200 OK
{
"status": "success",
"message": "Lote desarquivado.",
"data": {
"id": 9012,
"id_cliente": 4521,
"per_apur": "2026-06",
"status": "processado",
"arquivado_em": null,
"id_usuario_arquivou": null,
"nome_usuario_arquivou": null,
"motivo_arquivamento": null
}
}data é ReinfLoteOut. Idempotente (lote não arquivado equivale a no-op).
Erros: 403 credencial de API Key; 404 lote inexistente.
Escopo: reinf:write + sessão de usuário (API Key recusada)
GET /reinf/lotes/{lote_id}/eventos/{evento_id}
Detalhe de um evento REINF, incluindo o XML assinado enviado à Receita.
A resposta contém CPF/CNPJ do beneficiário
xml_evento traz o XML assinado do evento, com dado pessoal de terceiro (CPF/CNPJ e valores do sócio ou beneficiário). Trate a resposta como dado sensível ao consumir esta rota.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
lote_id | int | path | sim | ID do lote REINF |
evento_id | int | path | sim | ID do evento REINF |
Response 200 OK
{
"status": "success",
"message": "Evento recuperado com sucesso!",
"data": {
"id": 5501,
"id_lote": 9012,
"id_cliente": 4521,
"id_lancamento_lucro": 8801,
"tipo_evento": "R4010",
"id_evento_reinf": "R4010_00000000000000000123",
"status": "processado",
"fech_ret": null,
"id_evento_retificado": null,
"nr_recibo": "1.2.0000000000000000123",
"hash_evento": "a1b2c3d4",
"codigo_erro": null,
"descricao_erro": null,
"situacao_receita": null,
"data_hora_criacao": "2026-08-17T09:00:00",
"atualizado_em": "2026-08-17T09:03:40",
"xml_evento": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><evtRendimentos>...</evtRendimentos>"
}
}data é ReinfEventoDetailOut. 404 quando o lote ou o evento não existe.
Escopo: reinf:read
Schemas
ReinfTransmissaoCreate
Corpo de POST /reinf/transmitir.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
id_cliente | int | sim | ID do cliente declarante (customer.id). |
per_apur | str | sim | Período de apuração 'YYYY-MM' (7 caracteres). |
ids_lancamento_lucro | list[int] | sim | IDs dos lançamentos de lucro a transmitir - não vazia. |
ReinfFechamentoCreate
Corpo de POST /reinf/fechar-periodo.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
id_cliente | int | sim | ID do cliente declarante (customer.id). |
per_apur | str | sim | Período de apuração 'YYYY-MM' (7 caracteres). |
ReinfReaberturaCreate
Corpo de POST /reinf/periodos/reabrir. Mesmos campos de ReinfFechamentoCreate - é o mesmo evento R-4099 com o campo fechRet invertido; schema próprio só para documentar as duas operações separadamente no Swagger.
ReinfExclusaoCreate
Corpo de POST /reinf/eventos/{evento_id}/excluir.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
motivo | str | sim | Justificativa da exclusão, 1 a 500 caracteres. Só espaços é recusado (422). |
ReinfArquivamentoCreate
Corpo (opcional) de POST /reinf/lotes/{lote_id}/arquivar.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
motivo | str | null | não | Justificativa opcional, máx. 500 caracteres. Só espaços vira null. |
ReinfFechamentoExternoCreate
Corpo de POST /reinf/periodos/marcar-fechamento-externo. Estende ReinfFechamentoCreate.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
id_cliente | int | sim | Herdado de ReinfFechamentoCreate. |
per_apur | str | sim | Herdado de ReinfFechamentoCreate. |
motivo | str | sim | Base para a afirmação, 1 a 500 caracteres. |
nr_recibo_ecac | str | null | não | Recibo do R-4099 emitido pelo e-CAC, máx. 52 caracteres. Só espaços vira null. |
ReinfFechamentoExternoRemove
Corpo de POST /reinf/periodos/desmarcar-fechamento-externo. Só id_cliente e per_apur, herdados de ReinfFechamentoCreate.
ReinfLoteOut
Lote sem os XMLs, com contadores agregados de eventos - data das rotas de mutação de lote e item de GET /reinf/lotes.
| Campo | Tipo | Observações |
|---|---|---|
id | int | ID do lote. |
id_cliente | int | Cliente declarante. |
id_usuario | int | null | Autoria de criação. null se o usuário foi excluído. |
per_apur | str | Período de apuração 'YYYY-MM'. |
ambiente | str | producao ou producao_restrita. |
status | str | pendente, enviando, aguardando_processamento, processado, processado_com_erros, erro_envio. |
nr_protocolo | str | null | Protocolo de recepção do lote na Receita. |
tentativas_envio | int | Nº de tentativas de envio. |
tentativas_polling | int | Nº de tentativas de consulta. |
enviado_em | datetime | null | Quando o envio foi feito. |
processado_em | datetime | null | Quando a Receita respondeu. |
data_hora_criacao | datetime | null | Criação do lote. |
total_eventos | int | Quantidade de eventos no lote. |
eventos_processados | int | Eventos com desfecho processado. |
eventos_erro | int | Eventos em erro. |
tipo_resumo | str | null | O que o lote contém: Lucros, Fechamento, Reabertura, R-4099, Exclusão, ou combinação com " + ". Não indica desfecho, só conteúdo. |
arquivado_em | datetime | null | Preenchido quando o lote foi arquivado à mão. |
id_usuario_arquivou | int | null | Quem arquivou. |
nome_usuario_arquivou | str | null | Nome de quem arquivou, denormalizado. |
motivo_arquivamento | str | null | Justificativa do arquivamento. |
ReinfOcorrenciaOut
Uma ocorrência de recusa devolvida pela Receita, em nível de lote.
| Campo | Tipo | Observações |
|---|---|---|
codigo | str | null | Código da ocorrência. |
descricao | str | null | Descrição textual. |
tipo | str | null | Classificação (erro/aviso). |
localizacao | str | null | Ponto do XML apontado pela Receita. |
ReinfLoteDetailOut
data de GET /reinf/lotes/{lote_id}. Todos os campos de ReinfLoteOut, mais:
| Campo | Tipo | Observações |
|---|---|---|
eventos | list[ReinfEventoOut] | Eventos do lote, sem XML. |
ocorrencias | list[ReinfOcorrenciaOut] | Recusas de nível lote da última resposta conhecida. |
ReinfEventoOut
Evento sem o XML - usado em listagens e no detalhe do lote.
| Campo | Tipo | Observações |
|---|---|---|
id | int | ID do evento. |
id_lote | int | Lote ao qual pertence. |
id_cliente | int | Cliente declarante. |
id_lancamento_lucro | int | null | Deprecado: só o primeiro lançamento do grupo. Use GET /reinf/lotes/{id}/lancamentos. |
tipo_evento | str | R4010, R4020, R4040, R4080, R4099 ou R9000. |
id_evento_reinf | str | null | Identificador do evento atribuído pela Receita. |
status | str | pendente, enviado, processado, erro, retificado, excluido. |
fech_ret | int | null | 0 = Fechamento, 1 = Reabertura. Só em R-4099. |
id_evento_retificado | int | null | Evento que este corrige (retificador ou R-9000). null = original. |
nr_recibo | str | null | Recibo de aceite - única prova de que o evento foi declarado. |
hash_evento | str | null | Hash do XML enviado. |
codigo_erro | str | null | Código de recusa (nível lote, aplicado ao(s) evento(s) do lote em caso de 422). |
descricao_erro | str | null | Descrição da recusa. |
situacao_receita | int | null | Código de situação devolvido pela Receita. |
data_hora_criacao | datetime | null | Criação do evento. |
atualizado_em | datetime | null | Última atualização. |
ReinfEventoDetailOut
data de GET /reinf/lotes/{lote_id}/eventos/{evento_id}. Todos os campos de ReinfEventoOut, mais:
| Campo | Tipo | Observações |
|---|---|---|
xml_evento | str | null | XML assinado enviado à Receita, com CPF/CNPJ do beneficiário. |
ReinfLancamentoDoEventoOut
Item de GET /reinf/lotes/{lote_id}/lancamentos.
| Campo | Tipo | Observações |
|---|---|---|
id_evento | int | Evento ao qual o lançamento pertence. |
id | int | ID do lançamento (de lucro ou de plano de saúde, conforme origem). |
id_qsa_cliente | int | null | Sócio vinculado. |
nome_socio | str | null | Nome do sócio, denormalizado. null em R-4040 (beneficiário não identificado). |
competencia | str | null | Competência MM/YYYY do lançamento (snapshot). |
data_pagamento | date | null | Data do pagamento (snapshot). |
data_registro | date | null | Data de registro (snapshot). |
natureza_rendimento | str | null | Código da natureza (snapshot). |
valor_liquido | Decimal | null | Valor líquido declarado (snapshot). |
valor_bruto | Decimal | null | Valor bruto declarado (snapshot). |
valor_ata_utilizada | Decimal | null | Valor de ata utilizada (snapshot). |
valor_ir_retido | Decimal | null | IR retido declarado (snapshot). |
status | str | null | Status atual do lançamento (não é snapshot - reflete o estado de hoje). |
snapshot_disponivel | bool | false = vínculo anterior ao congelamento; os valores acima vêm nulos. |
origem | "lucro" | "plano_saude" | Discrimina a linha. |
operadora_nome | str | null | Só em origem="plano_saude". |
nome_dependente | str | null | Só em origem="plano_saude", quando o titular não é o sócio. |
valor_saude | Decimal | null | Só em origem="plano_saude". |
ReinfEventoDoLancamentoOut
data (item) de GET /reinf/eventos/por-lancamento (deprecada).
| Campo | Tipo | Observações |
|---|---|---|
id_lancamento_lucro | int | Lançamento de origem. |
per_apur | str | Competência do lote. |
evento | ReinfEventoOut | Evento vivo do lançamento. |
ReinfEventoDoHistoricoOut
Item de historico em ReinfHistoricoDoLancamentoOut - um elo da cadeia fiscal de um lançamento.
| Campo | Tipo | Observações |
|---|---|---|
id_evento | int | ID do evento. |
ordem | int | Posição na cadeia (1-based, do original à última retificação). |
marcacao | "original" | "retificado" | Deriva de id_evento_retificado. |
per_apur | str | Competência declarada por este elo. |
nr_recibo | str | null | Única prova de aceite - status_evento="processado" sem recibo não é declaração registrada. |
status_evento | str | Status do evento. |
transmitido_em | datetime | null | enviado_em do lote (o evento não tem carimbo próprio). |
snapshot_disponivel | bool | false ⇒ valores nulos, sem fallback ao lançamento vivo. |
congelado_em | datetime | null | Quando o snapshot foi congelado. |
competencia | str | null | Competência declarada (snapshot). |
data_pagamento | date | null | Data do pagamento (snapshot). |
natureza_rendimento | str | null | Código da natureza (snapshot). |
valor_bruto | Decimal | null | Valor bruto (snapshot). |
valor_liquido | Decimal | null | Valor líquido (snapshot). |
valor_ir_retido | Decimal | null | IR retido (snapshot). |
valor_ata_utilizada | Decimal | null | Ata utilizada (snapshot). |
valor_base_ir | Decimal | null | Sempre null nesta versão. |
ReinfHistoricoDoLancamentoOut
data (item) de GET /reinf/lancamentos/historico.
| Campo | Tipo | Observações |
|---|---|---|
id_lancamento_lucro | int | Lançamento de origem. |
marcacao | "original" | "retificado" | "excluido" | "nao_transmitido" | Estado do lançamento (não do evento). |
evento_vivo | ReinfEventoDoLancamentoOut | null | null quando não há evento vivo (inclusive logo após exclusão aceita). |
historico | list[ReinfEventoDoHistoricoOut] | Cadeia completa; [] quando nunca foi transmitido. |
ReinfLancamentoSaudeDeclaradoOut
Item de GET /reinf/lancamentos-saude/declarados.
| Campo | Tipo | Observações |
|---|---|---|
id_lancamento | int | ID do lançamento de plano de saúde. |
id_evento | int | Evento REINF ativo que o declara. |
status_evento | str | Status do evento. |
nr_recibo | str | null | Única prova de aceite. |
PaginatedReinfLotes
data de GET /reinf/lotes.
| Campo | Tipo | Observações |
|---|---|---|
items | list[ReinfLoteOut] | Lotes da página. |
total | int | Total do conjunto filtrado (já descontando ocultos, quando visibilidade=relevantes). |
total_pages | int | Total de páginas. |
current_page | int | Página atual. |
per_page | int | null | null quando não paginado. |
ocultos | int | Quantos lotes o recorte relevantes removeu. Sempre 0 em visibilidade=todos. |
ReinfStatusOut
data de GET /reinf/status.
| Campo | Tipo | Observações |
|---|---|---|
id_cliente | int | Cliente consultado. |
per_apur | str | Competência consultada. |
total_lotes | int | Total de lotes do período. |
total_eventos | int | Total de eventos do período. |
eventos_pendentes | int | Eventos ainda não enviados. |
eventos_enviados | int | Eventos enviados, sem desfecho ainda. |
eventos_processados | int | Eventos com desfecho da Receita. |
eventos_erro | int | Eventos em erro. |
periodo_fechado | bool | true quando o estado derivado do período é fechado. |
fechado_externamente | bool | true = fechado no e-CAC por fora (sem R-4099 nosso). |
lotes | list[ReinfLoteOut] | Lotes do período, para acompanhamento. |
ReinfFechamentoResumoOut
Último R-4099 aceito do período - usado dentro de ReinfEstadoPeriodoOut.
| Campo | Tipo | Observações |
|---|---|---|
id_evento | int | Evento do fechamento/reabertura. |
id_lote | int | null | Lote do evento. |
fech_ret | int | null | 0 = fechamento, 1 = reabertura. |
nr_recibo | str | null | Recibo de aceite. |
processado_em | datetime | null | Carimbo do lote (o evento não tem próprio). |
ReinfR4099TransitoOut
R-4099 com desfecho ainda desconhecido - usado dentro de ReinfEstadoPeriodoOut.
| Campo | Tipo | Observações |
|---|---|---|
id_evento | int | Evento em voo. |
id_lote | int | null | Lote do evento. |
status | str | null | Status do lote (pendente, enviado, aguardando_processamento). |
fech_ret | int | null | 0 = fechamento, 1 = reabertura. |
ReinfFechamentoExternoOut
A marcação de fechamento externo de um período - usado dentro de ReinfEstadoPeriodoOut.
| Campo | Tipo | Observações |
|---|---|---|
id_cliente | int | Cliente marcado. |
per_apur | str | Competência marcada. |
nr_recibo_ecac | str | null | Recibo emitido pela RFB via e-CAC (opcional). |
motivo | str | null | Justificativa registrada. |
id_usuario_marcou | int | null | Autoria. |
nome_usuario_marcou | str | null | Nome de quem marcou, denormalizado. |
marcado_em | datetime | null | Carimbo da marcação. |
ReinfPeriodoReabertoOut
Item de GET /reinf/periodos/reabertos.
| Campo | Tipo | Observações |
|---|---|---|
id_cliente | int | Cliente. |
nome_cliente | str | null | Nome de exibição do cliente. |
per_apur | str | Competência reaberta. |
reaberto_em | datetime | null | Quando a reabertura foi processada. |
dias_reaberto | int | null | Dias desde a reabertura. |
id_lote_reabertura | int | null | Lote da reabertura. |
ReinfLancamentoCorrecaoOut
Lançamento vinculado ao evento em correção - usado em lancamentos de ReinfRetificacaoAbertaOut.
| Campo | Tipo | Observações |
|---|---|---|
id | int | ID do lançamento. |
id_cliente | int | Cliente. |
id_qsa_cliente | int | null | Sócio vinculado. |
competencia | str | Competência do lançamento. |
natureza_rendimento | str | null | Código da natureza. |
valor_liquido | Decimal | null | Valor líquido atual. |
status | str | Status real após a operação (Em retificação ou Transmitido). |
ReinfRetificacaoAbertaOut
data de POST /reinf/eventos/{evento_id}/iniciar-retificacao e POST /reinf/eventos/{evento_id}/cancelar-retificacao.
| Campo | Tipo | Observações |
|---|---|---|
id_evento | int | Evento alvo. |
id_cliente | int | Cliente. |
per_apur | str | Competência do evento. |
tipo_evento | str | Tipo do evento alvo. |
nr_recibo | str | null | Recibo do evento alvo, referenciado pela retificação. |
status_lancamentos | str | Estado dos lançamentos após a operação. |
ja_estava_em_retificacao | bool | true quando o destrave já estava em vigor (duplo clique). |
lancamentos | list[ReinfLancamentoCorrecaoOut] | Lançamentos afetados. |
ReinfEstadoPeriodoOut
data de GET /reinf/periodos/estado e das rotas de fechamento externo.
| Campo | Tipo | Observações |
|---|---|---|
id_cliente | int | Cliente. |
per_apur | str | Competência. |
estado | "aberto" | "fechado" | "indeterminado" | Estado ternário do movimento. |
ultimo_fechamento | ReinfFechamentoResumoOut | null | Último R-4099 aceito. |
r4099_em_transito | ReinfR4099TransitoOut | null | R-4099 com desfecho desconhecido. |
fechado_externamente | bool | Procedência de estado="fechado": true = via e-CAC (marcação), false = R-4099 nosso. |
fechamento_externo | ReinfFechamentoExternoOut | null | Presente só quando fechado_externamente=true. |
reaberto_em | datetime | null | Quando o último R-4099 aceito é reabertura. |
dias_reaberto | int | null | Dias reaberto. |
pode_fechar | bool | Espelha os guards de fechar_periodo. |
motivo | str | null | Explicação de pode_fechar. |
ReinfEstadoClienteOut
Item de clientes em ReinfEstadoCompetenciaOut.
| Campo | Tipo | Observações |
|---|---|---|
id_cliente | int | Cliente. |
nome_cliente | str | null | Nome de exibição. |
estado | "aberto" | "fechado" | "indeterminado" | Mesmo eixo de ReinfEstadoPeriodoOut. |
reaberto | bool | true = aberto por reabertura (não confundir com "nunca fechado"). |
reaberto_em | datetime | null | Quando reaberto. |
dias_reaberto | int | null | Dias reaberto. |
pode_fechar | bool | Espelha o guard de fechamento. |
motivo | str | null | Explicação de pode_fechar. |
nr_recibo_ultimo_r4099 | str | null | Recibo do último R-4099 aceito (fechamento ou reabertura). |
fechado_externamente | bool | Procedência do estado="fechado" desta linha. |
id_lote_em_transito | int | null | Lote do R-4099 em voo, se houver. |
total_lancamentos | int | Lançamentos do cliente na competência. |
lancamentos_nao_transmitidos | int | Quantos ainda não foram transmitidos. |
ReinfEstadoCompetenciaOut
data de GET /reinf/periodos/estado-competencia.
| Campo | Tipo | Observações |
|---|---|---|
per_apur | str | Competência consultada. |
abertos | int | Clientes com estado aberto. |
fechados | int | Clientes com estado fechado. |
em_transito | int | Clientes com R-4099 em voo. |
reabertos | int | Subconjunto de abertos que está aberto por reabertura. |
clientes | list[ReinfEstadoClienteOut] | Uma linha por cliente elegível (matriz PJ, ativa, com sócio). |
ReinfFechamentoHistoricoOut
Item de itens em ReinfFechamentosPaginadosOut.
| Campo | Tipo | Observações |
|---|---|---|
id_cliente | int | Cliente. |
razao_social | str | Nome de exibição (nome fantasia, com fallback para a razão social). |
cnpj | str | CNPJ do cliente. |
per_apur | str | Competência fechada. |
nr_recibo | str | null | Recibo do fechamento (R-4099 nosso) ou do e-CAC (marcação). Nunca de reabertura. |
fechado_em | datetime | null | Quando o fechamento foi registrado. |
fechado_por | str | null | Nome de quem fechou. null se a autoria não foi registrada ou o usuário foi excluído. |
origem | "sistema" | "externo" | sistema = R-4099 nosso; externo = marcado via e-CAC. |
reaberto | bool | true quando o período foi fechado e depois reaberto. |
ReinfFechamentosPaginadosOut
data de GET /reinf/periodos/fechamentos.
| Campo | Tipo | Observações |
|---|---|---|
total | int | Total de registros que casam com os filtros. |
page | int | Página atual. |
per_page | int | Itens por página. |
itens | list[ReinfFechamentoHistoricoOut] | Registros da página. Envelope propositalmente distinto do de GET /reinf/lotes. |
Notas
- Toda resposta segue o envelope
{ status: "success", message, data }em sucesso e{ status: "error", message, details }em erro. As respostas de validação do FastAPI/Pydantic (422) seguem o formato padrão{ "detail": [...] }. - Nenhuma rota exige perfil. O escopo (
reinf:read/reinf:write) é a única guarda de "quem alcança o domínio"; cinco rotas de mutação, além disso, exigem sessão de usuário (recusam API Key) - ver o aviso de autenticação no topo desta página. - Ordem de rotas (FastAPI): os caminhos estáticos (
/transmitir,/fechar-periodo,/naturezas,/status,/lotes,/periodos/...) são declarados antes dos dinâmicos (/lotes/{lote_id}) para o casamento de rota funcionar corretamente. - Status de lote (
StatusLoteReinf):pendente,enviando,aguardando_processamento,processado,processado_com_erros,erro_envio. - Status de evento (
StatusEventoReinf):pendente,enviado,processado,erro,retificado,excluido. - Tipos de evento (
TipoEventoReinf):R4010(beneficiário pessoa física),R4020(pessoa jurídica),R4040(beneficiário não identificado),R4080(autorretenção, sem geração de XML nesta versão),R4099(fechamento/reabertura de período) eR9000(exclusão). O tipo R-4000 é decidido automaticamente pelo documento do sócio: CPF (11 dígitos) vira R-4010, CNPJ (14 dígitos) vira R-4020, documento ausente ou inválido vira R-4040. - R-4099 e R-9000 não são corrigíveis: não podem ser alvo de
iniciar-retificacao,retificarnemexcluir- o R-4099 é corrigido enviando outro R-4099, e não se exclui uma exclusão. GET /reinf/eventos/por-lancamentoestá deprecada e será removida em um release futuro. Ela é mantida apenas durante a janela entre o deploy do backend e o do front (que sobem separados); useGET /reinf/lancamentos/historicoem qualquer integração nova.- Nenhuma rota de listagem retorna o XML do evento. O XML assinado, com CPF/CNPJ do beneficiário, só sai em
GET /reinf/lotes/{lote_id}/eventos/{evento_id}(JSON) e emGET /reinf/lotes/{lote_id}/xmls(.zip). - Não existe exclusão de lote.
POST /reinf/lotes/{lote_id}/arquivarsó altera a apresentação (visibilidade na listagem); o registro fiscal (XML, hash e recibo) é imutável e permanece acessível por todas as demais rotas.