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/reinf

Escopos necessários

  • reinf:read - todas as rotas GET (consultas de período, status, lotes, eventos, histórico e catálogos).
  • reinf:write - todas as rotas POST (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.

  1. POST /reinf/eventos/{evento_id}/iniciar-retificacao - destrava os lançamentos para edição;
  2. o usuário corrige os lançamentos pelas rotas do domínio de lançamento de lucro (fora deste documento);
  3. POST /reinf/eventos/{evento_id}/retificar - congela o dado já editado, cria o lote e transmite. Ou POST /reinf/eventos/{evento_id}/cancelar-retificacao para 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âmetroTipoLocalObrigatórioDescrição
evento_idintpathsimID 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âmetroTipoLocalObrigatórioDescrição
evento_idintpathsimID 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âmetroTipoLocalObrigatórioDescrição
evento_idintpathsimID 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âmetroTipoLocalObrigatórioDescrição
evento_idintpathsimID 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âmetroTipoObrigatórioDescrição
id_clienteintsimID do cliente (customer.id).
per_apurstrsimPeríodo de apuração 'YYYY-MM'.

Request

GET /api/v1/reinf/periodos/estado?id_cliente=4521&per_apur=2026-06

Response 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âmetroTipoObrigatórioDescrição
per_apurstrsimPeríodo de apuração 'YYYY-MM'.

Request

GET /api/v1/reinf/periodos/estado-competencia?per_apur=2026-06

Response 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âmetroTipoDefaultDescrição
per_apurstr-Filtrar por competência 'YYYY-MM'. Omitido = todas.
id_clienteint-Filtrar por cliente. Omitido = todos.
pageint1Página (1-based, ≥ 1).
per_pageint25Itens por página (1-200).

Request

GET /api/v1/reinf/periodos/fechamentos?per_apur=2026-06&page=1&per_page=25

Response 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âmetroTipoObrigatórioDescrição
id_clienteintsimID do cliente (customer.id).
per_apurstrsimPeríodo de apuração 'YYYY-MM'.

Request

GET /api/v1/reinf/status?id_cliente=4521&per_apur=2026-06

Response 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âmetroTipoDefaultDescrição
id_clienteint-Filtra por cliente.
per_apurstr-Filtra por período 'YYYY-MM'.
statusstr-Filtra pelo status do lote: pendente, enviando, aguardando_processamento, processado, processado_com_erros, erro_envio.
visibilidaderelevantes | todostodostodos 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_bydata_hora_criacao | per_apur | statusdata_hora_criacaoColuna de ordenação (whitelist).
sort_dirasc | descdescDireção da ordenação.
pageint (≥ 1)1Página (1-based).
per_pageint (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=25

Response 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âmetroTipoObrigatórioDescrição
ids_lancamentolist[int]simIDs 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=8802

Response 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âmetroTipoObrigatórioDescrição
ids_lancamentolist[int]simIDs de lancamento_lucro (repita o parâmetro). Máx. 200 por chamada.

Request

GET /api/v1/reinf/lancamentos/historico?ids_lancamento=8801&ids_lancamento=8802

Response 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âmetroTipoObrigatórioDescrição
ids_lancamentolist[int]simIDs de lancamento_plano_saude (repita o parâmetro). Máx. 200 por chamada.

Request

GET /api/v1/reinf/lancamentos-saude/declarados?ids_lancamento=4401

Response 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âmetroTipoLocalObrigatórioDescrição
lote_idintpathsimID 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âmetroTipoLocalObrigatórioDescrição
lote_idintpathsimID 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âmetroTipoLocalObrigatórioDescrição
lote_idintpathsimID 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âmetroTipoLocalObrigatórioDescrição
lote_idintpathsimID do lote REINF
regenerar_xmlboolquerynãoDefault 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âmetroTipoLocalObrigatórioDescrição
lote_idintpathsimID 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âmetroTipoLocalObrigatórioDescrição
lote_idintpathsimID 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âmetroTipoLocalObrigatórioDescrição
lote_idintpathsimID 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âmetroTipoLocalObrigatórioDescrição
lote_idintpathsimID do lote REINF
evento_idintpathsimID 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.

CampoTipoObrigatórioObservações
id_clienteintsimID do cliente declarante (customer.id).
per_apurstrsimPeríodo de apuração 'YYYY-MM' (7 caracteres).
ids_lancamento_lucrolist[int]simIDs dos lançamentos de lucro a transmitir - não vazia.

ReinfFechamentoCreate

Corpo de POST /reinf/fechar-periodo.

CampoTipoObrigatórioObservações
id_clienteintsimID do cliente declarante (customer.id).
per_apurstrsimPerí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.

CampoTipoObrigatórioObservações
motivostrsimJustificativa da exclusão, 1 a 500 caracteres. Só espaços é recusado (422).

ReinfArquivamentoCreate

Corpo (opcional) de POST /reinf/lotes/{lote_id}/arquivar.

CampoTipoObrigatórioObservações
motivostr | nullnãoJustificativa opcional, máx. 500 caracteres. Só espaços vira null.

ReinfFechamentoExternoCreate

Corpo de POST /reinf/periodos/marcar-fechamento-externo. Estende ReinfFechamentoCreate.

CampoTipoObrigatórioObservações
id_clienteintsimHerdado de ReinfFechamentoCreate.
per_apurstrsimHerdado de ReinfFechamentoCreate.
motivostrsimBase para a afirmação, 1 a 500 caracteres.
nr_recibo_ecacstr | nullnãoRecibo 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.

CampoTipoObservações
idintID do lote.
id_clienteintCliente declarante.
id_usuarioint | nullAutoria de criação. null se o usuário foi excluído.
per_apurstrPeríodo de apuração 'YYYY-MM'.
ambientestrproducao ou producao_restrita.
statusstrpendente, enviando, aguardando_processamento, processado, processado_com_erros, erro_envio.
nr_protocolostr | nullProtocolo de recepção do lote na Receita.
tentativas_enviointNº de tentativas de envio.
tentativas_pollingintNº de tentativas de consulta.
enviado_emdatetime | nullQuando o envio foi feito.
processado_emdatetime | nullQuando a Receita respondeu.
data_hora_criacaodatetime | nullCriação do lote.
total_eventosintQuantidade de eventos no lote.
eventos_processadosintEventos com desfecho processado.
eventos_errointEventos em erro.
tipo_resumostr | nullO que o lote contém: Lucros, Fechamento, Reabertura, R-4099, Exclusão, ou combinação com " + ". Não indica desfecho, só conteúdo.
arquivado_emdatetime | nullPreenchido quando o lote foi arquivado à mão.
id_usuario_arquivouint | nullQuem arquivou.
nome_usuario_arquivoustr | nullNome de quem arquivou, denormalizado.
motivo_arquivamentostr | nullJustificativa do arquivamento.

ReinfOcorrenciaOut

Uma ocorrência de recusa devolvida pela Receita, em nível de lote.

CampoTipoObservações
codigostr | nullCódigo da ocorrência.
descricaostr | nullDescrição textual.
tipostr | nullClassificação (erro/aviso).
localizacaostr | nullPonto do XML apontado pela Receita.

ReinfLoteDetailOut

data de GET /reinf/lotes/{lote_id}. Todos os campos de ReinfLoteOut, mais:

CampoTipoObservações
eventoslist[ReinfEventoOut]Eventos do lote, sem XML.
ocorrenciaslist[ReinfOcorrenciaOut]Recusas de nível lote da última resposta conhecida.

ReinfEventoOut

Evento sem o XML - usado em listagens e no detalhe do lote.

CampoTipoObservações
idintID do evento.
id_loteintLote ao qual pertence.
id_clienteintCliente declarante.
id_lancamento_lucroint | nullDeprecado: só o primeiro lançamento do grupo. Use GET /reinf/lotes/{id}/lancamentos.
tipo_eventostrR4010, R4020, R4040, R4080, R4099 ou R9000.
id_evento_reinfstr | nullIdentificador do evento atribuído pela Receita.
statusstrpendente, enviado, processado, erro, retificado, excluido.
fech_retint | null0 = Fechamento, 1 = Reabertura. Só em R-4099.
id_evento_retificadoint | nullEvento que este corrige (retificador ou R-9000). null = original.
nr_recibostr | nullRecibo de aceite - única prova de que o evento foi declarado.
hash_eventostr | nullHash do XML enviado.
codigo_errostr | nullCódigo de recusa (nível lote, aplicado ao(s) evento(s) do lote em caso de 422).
descricao_errostr | nullDescrição da recusa.
situacao_receitaint | nullCódigo de situação devolvido pela Receita.
data_hora_criacaodatetime | nullCriação do evento.
atualizado_emdatetime | nullÚltima atualização.

ReinfEventoDetailOut

data de GET /reinf/lotes/{lote_id}/eventos/{evento_id}. Todos os campos de ReinfEventoOut, mais:

CampoTipoObservações
xml_eventostr | nullXML assinado enviado à Receita, com CPF/CNPJ do beneficiário.

ReinfLancamentoDoEventoOut

Item de GET /reinf/lotes/{lote_id}/lancamentos.

CampoTipoObservações
id_eventointEvento ao qual o lançamento pertence.
idintID do lançamento (de lucro ou de plano de saúde, conforme origem).
id_qsa_clienteint | nullSócio vinculado.
nome_sociostr | nullNome do sócio, denormalizado. null em R-4040 (beneficiário não identificado).
competenciastr | nullCompetência MM/YYYY do lançamento (snapshot).
data_pagamentodate | nullData do pagamento (snapshot).
data_registrodate | nullData de registro (snapshot).
natureza_rendimentostr | nullCódigo da natureza (snapshot).
valor_liquidoDecimal | nullValor líquido declarado (snapshot).
valor_brutoDecimal | nullValor bruto declarado (snapshot).
valor_ata_utilizadaDecimal | nullValor de ata utilizada (snapshot).
valor_ir_retidoDecimal | nullIR retido declarado (snapshot).
statusstr | nullStatus atual do lançamento (não é snapshot - reflete o estado de hoje).
snapshot_disponivelboolfalse = vínculo anterior ao congelamento; os valores acima vêm nulos.
origem"lucro" | "plano_saude"Discrimina a linha.
operadora_nomestr | nullSó em origem="plano_saude".
nome_dependentestr | nullSó em origem="plano_saude", quando o titular não é o sócio.
valor_saudeDecimal | nullSó em origem="plano_saude".

ReinfEventoDoLancamentoOut

data (item) de GET /reinf/eventos/por-lancamento (deprecada).

CampoTipoObservações
id_lancamento_lucrointLançamento de origem.
per_apurstrCompetência do lote.
eventoReinfEventoOutEvento vivo do lançamento.

ReinfEventoDoHistoricoOut

Item de historico em ReinfHistoricoDoLancamentoOut - um elo da cadeia fiscal de um lançamento.

CampoTipoObservações
id_eventointID do evento.
ordemintPosição na cadeia (1-based, do original à última retificação).
marcacao"original" | "retificado"Deriva de id_evento_retificado.
per_apurstrCompetência declarada por este elo.
nr_recibostr | nullÚnica prova de aceite - status_evento="processado" sem recibo não é declaração registrada.
status_eventostrStatus do evento.
transmitido_emdatetime | nullenviado_em do lote (o evento não tem carimbo próprio).
snapshot_disponivelboolfalse ⇒ valores nulos, sem fallback ao lançamento vivo.
congelado_emdatetime | nullQuando o snapshot foi congelado.
competenciastr | nullCompetência declarada (snapshot).
data_pagamentodate | nullData do pagamento (snapshot).
natureza_rendimentostr | nullCódigo da natureza (snapshot).
valor_brutoDecimal | nullValor bruto (snapshot).
valor_liquidoDecimal | nullValor líquido (snapshot).
valor_ir_retidoDecimal | nullIR retido (snapshot).
valor_ata_utilizadaDecimal | nullAta utilizada (snapshot).
valor_base_irDecimal | nullSempre null nesta versão.

ReinfHistoricoDoLancamentoOut

data (item) de GET /reinf/lancamentos/historico.

CampoTipoObservações
id_lancamento_lucrointLançamento de origem.
marcacao"original" | "retificado" | "excluido" | "nao_transmitido"Estado do lançamento (não do evento).
evento_vivoReinfEventoDoLancamentoOut | nullnull quando não há evento vivo (inclusive logo após exclusão aceita).
historicolist[ReinfEventoDoHistoricoOut]Cadeia completa; [] quando nunca foi transmitido.

ReinfLancamentoSaudeDeclaradoOut

Item de GET /reinf/lancamentos-saude/declarados.

CampoTipoObservações
id_lancamentointID do lançamento de plano de saúde.
id_eventointEvento REINF ativo que o declara.
status_eventostrStatus do evento.
nr_recibostr | nullÚnica prova de aceite.

PaginatedReinfLotes

data de GET /reinf/lotes.

CampoTipoObservações
itemslist[ReinfLoteOut]Lotes da página.
totalintTotal do conjunto filtrado (já descontando ocultos, quando visibilidade=relevantes).
total_pagesintTotal de páginas.
current_pageintPágina atual.
per_pageint | nullnull quando não paginado.
ocultosintQuantos lotes o recorte relevantes removeu. Sempre 0 em visibilidade=todos.

ReinfStatusOut

data de GET /reinf/status.

CampoTipoObservações
id_clienteintCliente consultado.
per_apurstrCompetência consultada.
total_lotesintTotal de lotes do período.
total_eventosintTotal de eventos do período.
eventos_pendentesintEventos ainda não enviados.
eventos_enviadosintEventos enviados, sem desfecho ainda.
eventos_processadosintEventos com desfecho da Receita.
eventos_errointEventos em erro.
periodo_fechadobooltrue quando o estado derivado do período é fechado.
fechado_externamentebooltrue = fechado no e-CAC por fora (sem R-4099 nosso).
loteslist[ReinfLoteOut]Lotes do período, para acompanhamento.

ReinfFechamentoResumoOut

Último R-4099 aceito do período - usado dentro de ReinfEstadoPeriodoOut.

CampoTipoObservações
id_eventointEvento do fechamento/reabertura.
id_loteint | nullLote do evento.
fech_retint | null0 = fechamento, 1 = reabertura.
nr_recibostr | nullRecibo de aceite.
processado_emdatetime | nullCarimbo do lote (o evento não tem próprio).

ReinfR4099TransitoOut

R-4099 com desfecho ainda desconhecido - usado dentro de ReinfEstadoPeriodoOut.

CampoTipoObservações
id_eventointEvento em voo.
id_loteint | nullLote do evento.
statusstr | nullStatus do lote (pendente, enviado, aguardando_processamento).
fech_retint | null0 = fechamento, 1 = reabertura.

ReinfFechamentoExternoOut

A marcação de fechamento externo de um período - usado dentro de ReinfEstadoPeriodoOut.

CampoTipoObservações
id_clienteintCliente marcado.
per_apurstrCompetência marcada.
nr_recibo_ecacstr | nullRecibo emitido pela RFB via e-CAC (opcional).
motivostr | nullJustificativa registrada.
id_usuario_marcouint | nullAutoria.
nome_usuario_marcoustr | nullNome de quem marcou, denormalizado.
marcado_emdatetime | nullCarimbo da marcação.

ReinfPeriodoReabertoOut

Item de GET /reinf/periodos/reabertos.

CampoTipoObservações
id_clienteintCliente.
nome_clientestr | nullNome de exibição do cliente.
per_apurstrCompetência reaberta.
reaberto_emdatetime | nullQuando a reabertura foi processada.
dias_reabertoint | nullDias desde a reabertura.
id_lote_reaberturaint | nullLote da reabertura.

ReinfLancamentoCorrecaoOut

Lançamento vinculado ao evento em correção - usado em lancamentos de ReinfRetificacaoAbertaOut.

CampoTipoObservações
idintID do lançamento.
id_clienteintCliente.
id_qsa_clienteint | nullSócio vinculado.
competenciastrCompetência do lançamento.
natureza_rendimentostr | nullCódigo da natureza.
valor_liquidoDecimal | nullValor líquido atual.
statusstrStatus 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.

CampoTipoObservações
id_eventointEvento alvo.
id_clienteintCliente.
per_apurstrCompetência do evento.
tipo_eventostrTipo do evento alvo.
nr_recibostr | nullRecibo do evento alvo, referenciado pela retificação.
status_lancamentosstrEstado dos lançamentos após a operação.
ja_estava_em_retificacaobooltrue quando o destrave já estava em vigor (duplo clique).
lancamentoslist[ReinfLancamentoCorrecaoOut]Lançamentos afetados.

ReinfEstadoPeriodoOut

data de GET /reinf/periodos/estado e das rotas de fechamento externo.

CampoTipoObservações
id_clienteintCliente.
per_apurstrCompetência.
estado"aberto" | "fechado" | "indeterminado"Estado ternário do movimento.
ultimo_fechamentoReinfFechamentoResumoOut | nullÚltimo R-4099 aceito.
r4099_em_transitoReinfR4099TransitoOut | nullR-4099 com desfecho desconhecido.
fechado_externamenteboolProcedência de estado="fechado": true = via e-CAC (marcação), false = R-4099 nosso.
fechamento_externoReinfFechamentoExternoOut | nullPresente só quando fechado_externamente=true.
reaberto_emdatetime | nullQuando o último R-4099 aceito é reabertura.
dias_reabertoint | nullDias reaberto.
pode_fecharboolEspelha os guards de fechar_periodo.
motivostr | nullExplicação de pode_fechar.

ReinfEstadoClienteOut

Item de clientes em ReinfEstadoCompetenciaOut.

CampoTipoObservações
id_clienteintCliente.
nome_clientestr | nullNome de exibição.
estado"aberto" | "fechado" | "indeterminado"Mesmo eixo de ReinfEstadoPeriodoOut.
reabertobooltrue = aberto por reabertura (não confundir com "nunca fechado").
reaberto_emdatetime | nullQuando reaberto.
dias_reabertoint | nullDias reaberto.
pode_fecharboolEspelha o guard de fechamento.
motivostr | nullExplicação de pode_fechar.
nr_recibo_ultimo_r4099str | nullRecibo do último R-4099 aceito (fechamento ou reabertura).
fechado_externamenteboolProcedência do estado="fechado" desta linha.
id_lote_em_transitoint | nullLote do R-4099 em voo, se houver.
total_lancamentosintLançamentos do cliente na competência.
lancamentos_nao_transmitidosintQuantos ainda não foram transmitidos.

ReinfEstadoCompetenciaOut

data de GET /reinf/periodos/estado-competencia.

CampoTipoObservações
per_apurstrCompetência consultada.
abertosintClientes com estado aberto.
fechadosintClientes com estado fechado.
em_transitointClientes com R-4099 em voo.
reabertosintSubconjunto de abertos que está aberto por reabertura.
clienteslist[ReinfEstadoClienteOut]Uma linha por cliente elegível (matriz PJ, ativa, com sócio).

ReinfFechamentoHistoricoOut

Item de itens em ReinfFechamentosPaginadosOut.

CampoTipoObservações
id_clienteintCliente.
razao_socialstrNome de exibição (nome fantasia, com fallback para a razão social).
cnpjstrCNPJ do cliente.
per_apurstrCompetência fechada.
nr_recibostr | nullRecibo do fechamento (R-4099 nosso) ou do e-CAC (marcação). Nunca de reabertura.
fechado_emdatetime | nullQuando o fechamento foi registrado.
fechado_porstr | nullNome 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.
reabertobooltrue quando o período foi fechado e depois reaberto.

ReinfFechamentosPaginadosOut

data de GET /reinf/periodos/fechamentos.

CampoTipoObservações
totalintTotal de registros que casam com os filtros.
pageintPágina atual.
per_pageintItens por página.
itenslist[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) e R9000 (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, retificar nem excluir - o R-4099 é corrigido enviando outro R-4099, e não se exclui uma exclusão.
  • GET /reinf/eventos/por-lancamento está 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); use GET /reinf/lancamentos/historico em 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 em GET /reinf/lotes/{lote_id}/xmls (.zip).
  • Não existe exclusão de lote. POST /reinf/lotes/{lote_id}/arquivar só 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.