DCTFWeb: Emissão
Endpoints da WebApiAlcance que emitem e coletam guias e recibos junto ao Integra Contador (Serpro). Cobrem a emissão de DCTFWeb (DARF) e PGDAS-D (DAS do Simples Nacional) e o download dos recibos de transmissão, para um único CNPJ ou para toda a carteira interna de clientes - em janela anual (últimos N anos, máx. 3) ou em uma competência mensal específica.
São duas famílias de rota sob o mesmo prefixo, com propósitos diferentes:
- Emissão sob demanda -
POST /dctfweb/emissao/guias/emitiremite uma guia, para um contribuinte, com os sistemas de origem escolhidos por quem chama. É a única rota de emissão em queidsSistemaOrigemecategoriasão parâmetros do corpo. - Coleta em lote - as cinco rotas
baixar-*percorrem CNPJ × competência comidsSistemaOrigemliteral no código ([1, 6, 7]ou[8]) e categoria fixa emGERAL_MENSAL. Servem à automação agendada.
O que é emitido ou coletado aqui é gravado nos registros internos de Guias e Recibos, de onde a interface lê depois.
Todos os endpoints exigem autenticação. Veja Autenticação para o fluxo de API Key. O Swagger oficial está em api.contabilidadealcance.com.br/docs (tags DCTFWeb: Emissão de Guias e DCTFWeb: Emissão de Recibos).
Caminhos antigos `/integra-contador/radar/*` continuam vivos, porém deprecados
Cada rota de coleta em lote tem um alias sob /api/v1/integra-contador/radar/... que serve o mesmo handler - migrar não muda requisição nem resposta:
| Caminho legado (deprecado) | Caminho novo |
|---|---|
POST /integra-contador/radar/guias/baixar-todas | POST /dctfweb/emissao/guias/baixar-todas |
POST /integra-contador/radar/guias/baixar-mensal/esocial | POST /dctfweb/emissao/guias/baixar-mensal/esocial |
POST /integra-contador/radar/guias/baixar-mensal/mit | POST /dctfweb/emissao/guias/baixar-mensal/mit |
POST /integra-contador/radar/recibos/baixar-todas | POST /dctfweb/emissao/recibos/baixar-todas |
POST /integra-contador/radar/recibos/baixar-mensal | POST /dctfweb/emissao/recibos/baixar-mensal |
Os alias exigem o escopo antigo integra_contador:write e serão removidos numa versão futura. /integra-contador/radar/pagamentos/* não foi movido - continua onde estava.
POST /dctfweb/emissao/guias/emitir não entra nessa tabela: ela nasceu sob o prefixo consolidado e nunca existiu em outro caminho - não há /integra-contador/radar/guias/emitir.
Base path
/api/v1/dctfweb/emissaoEscopos necessários
dctfweb:write- todas as rotas desta página sãoPOST.
O recurso vem do primeiro segmento do path (dctfweb) e a ação, do método HTTP. Tokens emitidos antes da consolidação não carregam dctfweb:write - relogue ou atualize a API Key antes de migrar.
Emitir NÃO exige perfil de gestão nem sessão de usuário
As seis rotas desta página pedem apenas token válido + dctfweb:write. Qualquer perfil (funcionario, gestor, diretoria, administrador) emite, e API Key é aceita.
É deliberadamente diferente da Transmissão, que acumula perfil administrador/diretoria e recusa API Key: emitir guia não declara nada ao fisco - gera um documento de arrecadação a partir do que já foi declarado, e repetir a operação não tem efeito fiscal. Aplicar aqui o guard da transmissão bloquearia a automação e o trabalho diário do operacional.
O que não cai é a autorização de dado: o CNPJ precisa pertencer a um cliente do escritório (403 caso contrário). Escopo e perfil dizem o que o chamador pode fazer; essa checagem diz sobre quem.
Execução síncrona, não Celery
A emissão e a coleta não enfileiram tasks Celery. Cada requisição executa a orquestração das chamadas ao Serpro de forma síncrona, porém fora do event loop (anyio.to_thread.run_sync), e só responde quando tudo termina. Para carteiras grandes (usar_lista_interna=true), a chamada pode ser demorada: percorre CNPJ × competência sequencialmente.
As rotas `baixar-*` NÃO usam o envelope padrão - `emitir` usa
Diferente do resto da WebApi, as cinco rotas de coleta em lote declaram response_model próprio e devolvem o objeto direto, sem { status, message, data }. O corpo de sucesso é { summary, guias, erros } (guias) ou { summary, recibos } (recibos).
POST /dctfweb/emissao/guias/emitir é a exceção: responde com o envelope padrão { status, message, data }, como a transmissão e o resto da API.
Já os erros HTTP passam pelo handler global da WebApi e saem como { "message": ... } — nunca { "detail": ... }, com uma exceção: a validação do corpo pelo FastAPI/Pydantic (422) sai no formato nativo { "detail": [ { "loc", "msg", "type" } ] }. Nas descrições de erro abaixo, o texto citado é o conteúdo do message.
Não confunda com o campo detail de cada item de erros[] nas rotas de lote: aquele é outra coisa — a falha de um CNPJ específico dentro de uma resposta 200 OK.
Qual rota de guia usar
As três rotas de guia coexistem e não se substituem:
| Rota | idsSistemaOrigem | categoria | Alvo | Para que serve |
|---|---|---|---|---|
POST /emissao/guias/emitir | parâmetro (ou omitido) | parâmetro | 1 CNPJ, 1 competência | Emissão sob demanda, quando quem emite escolhe as origens. |
POST /emissao/guias/baixar-mensal/esocial | fixo [1, 6, 7] | fixa GERAL_MENSAL | 1 CNPJ ou a carteira | Fechamento mensal da folha, em lote (automação agendada). |
POST /emissao/guias/baixar-mensal/mit | fixo [8] | fixa GERAL_MENSAL | 1 CNPJ ou a carteira | Fechamento mensal fiscal, em lote (automação agendada). |
baixar-todas é a variante de janela anual da coleta em lote (até 3 anos), também com origens fixas.
Na prática: lote e rotina → baixar-*; uma guia específica, com as origens que o caso pede → emitir.
Endpoints
POST /dctfweb/emissao/guias/emitir
Emite a guia (DARF) da DCTFWeb de um contribuinte, em uma competência, com os sistemas de origem configuráveis. É a versão parametrizável da emissão: idsSistemaOrigem e categoria vêm do corpo, e não do código.
Do lado do servidor a rota executa, nesta ordem:
| # | Etapa | O que acontece |
|---|---|---|
| 1 | Autorização de dado | O cnpj é resolvido contra a carteira interna (busca por dígitos). Não sendo cliente, 403. |
| 2 | CONSRECIBO32 (acionamento /Consultar) | Best-effort: busca o numeroReciboEntrega do período. Pulada quando o recibo vem explícito no corpo. |
| 3 | GERARGUIA31 (acionamento /Emitir) | Emite a guia. É aqui que idsSistemaOrigem entra - ou não entra, quando omitido. |
| 4 | Persistência | Best-effort: grava a guia em Guias e registra a atividade do cliente. |
Parâmetros
Sem parâmetros de rota ou query - os dados vão no corpo (DctfwebEmitirGuiaRequest, ver DctfwebEmitirGuiaRequest). Obrigatórios: cnpj e anoPA; mesPA é obrigatório em todas as categorias exceto as de 13º salário.
Request - corpo mínimo (guia com todas as receitas do período):
{
"cnpj": "27898481000150",
"anoPA": "2026",
"mesPA": "04"
}Com origens escolhidas:
{
"cnpj": "27.898.481/0001-50",
"categoria": "GERAL_MENSAL",
"anoPA": "2026",
"mesPA": "04",
"idsSistemaOrigem": [1, 6, 7]
}Response 200 OK
{
"status": "success",
"message": "Guia emitida com sucesso!",
"data": {
"id_guia": 8830,
"id_cliente": 123,
"cnpj": "27898481000150",
"categoria": "GERAL_MENSAL",
"competencia": "2026-04",
"idsSistemaOrigem": [1, 6, 7],
"setor": "pessoal",
"numero_recibo": "12.34.56.78-90",
"arquivo_nome": "dctfweb_guia_27898481000150_2026-04.pdf",
"tem_pdf": true,
"mensagem": "Guia emitida com sucesso."
}
}Omitir `idsSistemaOrigem` NÃO é o mesmo que enviar lista vazia
É a armadilha nº 1 desta rota, e vem da semântica do próprio Integra Contador ("quando informado, a guia será gerada contendo apenas as receitas oriundas do(s) sistema(s) de origem especificado(s)"):
- Campo omitido (ausente do corpo, ou explicitamente
null) → a chave não entra no payload enviado à Receita, e a guia sai com TODAS as receitas do período. É o default e é um estado legítimo. Na resposta,idsSistemaOrigemvoltanull. - Lista com códigos → a guia contém apenas as receitas daqueles sistemas.
- Lista vazia (
[]) →422. Uma guia de nenhuma origem não existe, e a API recusa antes de chamar o Serpro:"'idsSistemaOrigem' não pode ser uma lista vazia — informe ao menos um sistema de origem, ou omita o campo para gerar a guia com todas as receitas. Códigos aceitos: 1, 5, 6, 7, 8."
Na interface: um seletor "todas as origens" precisa não enviar o campo. Desmarcar tudo não pode virar [] no corpo.
Tipagem estrita: `"1"` e `true` tomam 422, não são coeridos
O campo é declarado como lista de StrictInt, e não de int. Isso desliga a coerção que o Pydantic aplicaria por padrão - o comportamento que a maioria dos integradores espera:
| Enviado | Resultado |
|---|---|
[1, 6, 7] | 200 - aceito. |
["1", "6", "7"] | 422 - string não é inteiro; não vira [1, 6, 7]. |
[true] | 422 - em Python True é int; sem o modo estrito viraria silenciosamente o código 1 (eSocial) e a Receita emitiria uma guia de folha sem ninguém ter pedido. |
[1.0] | 422 - float não é inteiro estrito. |
"167" | 422 - string iteraria como ["1", "6", "7"] e passaria por acidente. |
[99] | 422 - fora do domínio oficial. |
[1, 1] | 422 - código repetido. |
A mensagem do 422 sempre lista os códigos aceitos (1, 5, 6, 7, 8). Envie inteiros JSON, sem aspas.
`setor` é DERIVADO, não informado
Não existe campo setor na requisição. Ele é calculado a partir das origens e gravado no registro da guia:
fiscal- somente quando a guia é exclusivamente MIT, isto é,idsSistemaOrigem == [8].pessoal- todo o resto, inclusive o campo omitido (guia com todas as receitas), porque nesses casos a parte previdenciária está sempre presente e é o setor que trata a guia.
É um rótulo organizacional (qual setor do escritório cuida da guia), herdado do registro de guias, que só admite esses dois valores - não há "misto". Uma guia com todas as receitas é literalmente as duas coisas, e aparece como pessoal.
A resposta NÃO traz o PDF - traz o `id_guia`
O base64 do DARF não é devolvido aqui. O PDF é persistido no registro de guias e sai por GET /dctfweb/guias/{guia_id}/pdf (binário). O elo entre as duas chamadas é o id_guia.
id_guia vem null apenas quando a persistência falha - a emissão na Receita já terá ocorrido de qualquer forma (a gravação é best-effort, de propósito: uma falha de banco não pode transformar um 200 num 500 e fazer o operador emitir tudo de novo). Nesse caso o PDF não fica recuperável por id; reemita.
`200` com `tem_pdf: false` é possível
Quando a Receita aceita a emissão mas não devolve o PDF (e não é o caso de "sem débitos", que vira 422), a resposta é 200 com tem_pdf: false, arquivo_nome: null e mensagem: "A Receita aceitou a emissão, mas não devolveu o PDF da guia.". O registro correspondente é gravado com status Falha, para não parecer baixável na listagem. Sempre leia tem_pdf antes de oferecer o download.
Erros
| HTTP | Quando | Corpo |
|---|---|---|
422 | Validação do corpo (campo desconhecido, idsSistemaOrigem inválido, regra condicional da categoria) | Formato nativo do FastAPI: { "detail": [ { "loc", "msg", "type" } ] }. |
422 | Documento sem dígitos | { "message": "Informe um CNPJ/CPF válido." } |
403 | CNPJ não é cliente do escritório | { "message": "O documento informado não pertence a nenhum cliente do escritório. A emissão de guia da DCTFWeb só é permitida para clientes cadastrados." } |
422 | Sem débitos a pagar (GUIA03) | Ver o aviso abaixo - o corpo tem duas formas. |
422, 502, ... | Recusa do Serpro classificada | { "message": { "classe", "codigo", "mensagem", "acionamento", "codigos" } } |
O status de uma recusa do Serpro não é o status do gateway: ele é derivado da classe do erro (negocio → 422, transitorio → 502, desconhecido → 502, ...). A tabela completa de classes, o catálogo de códigos (GUIA03, MG10, MG12/MG19/MG21, ...) e o formato do objeto de erro estão em DCTFWeb: Transmissão - Erros do Serpro; o mecanismo é o mesmo nas duas superfícies. O corpo cru do gateway nunca é repassado.
"Não há débitos com saldo a pagar" chega por dois caminhos
O mesmo fato - o período não tem o que pagar - pode voltar do Serpro de duas maneiras, e as duas terminam em 422, com corpos diferentes:
- Quando vem como erro codificado (
GUIA03), o corpo é o objeto de erro tipado:{ "message": { "classe": "negocio", "codigo": "GUIA03", "mensagem": "Não há débitos com saldo a pagar para emissão da guia de pagamento.", ... } }. - Quando o Serpro manda a mesma informação como
Aviso/Sucesso(aí não há erro a classificar), a detecção é pelo texto e o corpo é a string:{ "message": "Não há débitos com saldo a pagar para emissão da guia de pagamento." }.
Trate 422 + esse texto como desfecho normal de quem não tem débito no período, não como falha da integração. Ao ler o corpo, aceite message como string ou objeto.
`numeroReciboEntrega` normalmente é dispensável
A rota consulta o recibo do período sozinha (CONSRECIBO32) e o injeta no payload da guia. Informe o campo explicitamente só quando houver mais de uma declaração no período e a Receita exigir a escolha (código MG10) - o valor informado vence o consultado, e evita a chamada extra.
A consulta é best-effort: se ela falhar, a emissão segue sem recibo (a Receita usa a declaração ativa do período, que é o caso comum). Uma instabilidade num acionamento auxiliar não derruba a emissão pedida. O que foi efetivamente usado volta em numero_recibo - null quando não se obteve nenhum.
Emitir é repetível - e o servidor já repete sozinho
O acionamento /Emitir é tratado como idempotente: timeout ou falha de rede fazem a WebApi repetir a chamada com backoff (até 3 tentativas por padrão) antes de desistir. Esgotadas as tentativas, o desfecho é 502 (classe transitorio), não 504.
Por isso não existe estado indeterminado nesta rota - a dúvida "entrou ou não entrou?" que domina a Transmissão não se aplica aqui: emitir guia não registra nada no fisco, e repetir a operação é seguro. Reemitir depois de um erro é uma resposta válida.
Cada chamada ao Serpro tem timeout próprio (60s por padrão) e roda fora do event loop; com as retentativas, uma emissão problemática pode levar alguns minutos - dimensione o timeout do seu cliente HTTP.
Escopo: dctfweb:write (sem exigência de perfil; API Key aceita)
POST /dctfweb/emissao/guias/baixar-todas
Emite/lista todas as guias (DCTFWeb e PGDAS-D) dos últimos N anos (máx. 3, equivalente a até 36 competências retroativas a partir do mês atual). Aceita um único CNPJ (contribuinte) ou toda a carteira interna (usar_lista_interna=true).
Parâmetros
Sem parâmetros de rota ou query - os dados vão no corpo (GuiasDownloadRequest). Para esta rota, os campos relevantes são contribuinte ou usar_lista_interna, e anos (1-3, default 1).
Request
{
"contribuinte": { "tipo": 2, "numero": "27898481000150" },
"anos": 1
}Alternativa - toda a carteira:
{
"usar_lista_interna": true,
"anos": 1
}Response 200 OK
{
"summary": {
"total": 24,
"abertas": 0,
"pagas": 0,
"vencidas": 0,
"porTipo": { "DCTF": 12, "PGDAS": 12 }
},
"guias": [
{
"id": "DCTFWeb:27898481000150:2025-06",
"tipo": "DCTF",
"competencia": "2025-06",
"valor": 0.0,
"dataVencimento": null,
"status": "desconhecida",
"clienteNumero": "27898481000150",
"clienteNome": null,
"descricao": "DCTFWeb - 2025-06",
"codigoBarras": null,
"dataGeracao": "2026-07-03",
"observacoes": null,
"origem": "DCTFWeb",
"extras": { "emitir": {}, "pdfGuiaPath": "..." }
}
],
"erros": []
}Erros por CNPJ/competência não interrompem a coleta: são acumulados em erros[] e a resposta ainda é 200 OK. Se nenhum CNPJ for resolvido, retorna 422 com "Informe 'contribuinte.numero' (CNPJ), ou 'cnpjs', ou 'usar_lista_interna=true'.". Falha global na orquestração retorna 500 com message: "Erro ao coletar guias".
Escopo: dctfweb:write
POST /dctfweb/emissao/guias/baixar-mensal/esocial
Emite/lista guias (DCTFWeb e PGDAS-D) de uma única competência, para 1 CNPJ ou toda a carteira. É a variante eSocial: a geração do DARF usa idsSistemaOrigem = [1, 6, 7] (eSocial + Reinf CP + Reinf RET).
Parâmetros
Sem parâmetros de rota ou query - corpo em GuiasDownloadRequest. Exige a competência via competencia ("AAAA-MM") ou o par ano + mes, e o alvo via contribuinte ou usar_lista_interna.
Request
{
"contribuinte": { "tipo": 2, "numero": "27898481000150" },
"competencia": "2025-06"
}Response 200 OK
Mesmo envelope de baixar-todas (summary + guias + erros), restrito à competência informada.
{
"summary": {
"total": 2,
"abertas": 0,
"pagas": 0,
"vencidas": 0,
"porTipo": { "DCTF": 1, "PGDAS": 1 }
},
"guias": [
{
"id": "DCTFWeb:27898481000150:2025-06",
"tipo": "DCTF",
"competencia": "2025-06",
"valor": 0.0,
"dataVencimento": null,
"status": "desconhecida",
"clienteNumero": "27898481000150",
"clienteNome": null,
"descricao": "DCTFWeb - 2025-06",
"codigoBarras": null,
"dataGeracao": "2026-07-03",
"observacoes": null,
"origem": "DCTFWeb",
"extras": { "emitir": {}, "pdfGuiaPath": "..." }
}
],
"erros": []
}Competência mal formada retorna 422 ("Formato de 'competencia' inválido. Use 'YYYY-MM'."); ausência de competência e de ano/mes válidos retorna 422 ("Informe 'competencia' (YYYY-MM) ou 'ano' e 'mes' válidos."). Erro global retorna 500 com message: "Erro ao coletar guias mensais".
Para CNPJs de matriz (contêm 0001) resolvidos pela carteira interna, é registrada uma atividade DCTFWeb por cliente, com status "Concluído" ou "Falha".
Escopo: dctfweb:write
POST /dctfweb/emissao/guias/baixar-mensal/mit
Idêntico à variante eSocial, porém na variante MIT (Módulo de Inclusão de Tributos): a geração do DARF usa idsSistemaOrigem = [8]. A coleta PGDAS-D é a mesma nas duas variantes.
Parâmetros
Sem parâmetros de rota ou query - corpo em GuiasDownloadRequest, mesmas regras de competência e de alvo da variante eSocial.
Request
{
"usar_lista_interna": true,
"competencia": "2025-06"
}Response 200 OK
Mesmo envelope { summary, guias, erros } da variante eSocial. Também registra atividade DCTFWeb por cliente matriz da carteira interna. Erro global retorna 500 com message: "Erro ao coletar guias mensais".
Escopo: dctfweb:write
POST /dctfweb/emissao/recibos/baixar-todas
Coleta/lista os recibos de transmissão dos últimos N anos (anos, 1 a 3), para um único CNPJ ou toda a carteira interna. Percorre todas as competências mensais do intervalo e, para cada CNPJ, consulta o recibo da DCTFWeb no Serpro.
Parâmetros
Sem parâmetros de rota ou query - corpo em RecibosDownloadRequest: contribuinte ou usar_lista_interna: true, com anos opcional (default 1).
Request
{
"contribuinte": { "tipo": 2, "numero": "27898481000150" },
"anos": 1
}Response 200 OK
{
"summary": {
"total": 12,
"abertas": 0,
"pagas": 0,
"vencidas": 0,
"porTipo": { "DCTF": 12 }
},
"recibos": [
{
"id": "DCTFWeb:27898481000150:2025-06",
"tipo": "DCTF",
"competencia": "2025-06",
"clienteNumero": "27898481000150",
"descricao": "Recibo DCTFWeb - 2025-06",
"origem": "DCTFWeb",
"dataGeracao": "2026-07-03",
"pdfPath": "/caminho/RECIBO_DCTF/.../DCTFWeb_27898481000150_2025-06.pdf",
"extras": { "consulta": {} }
}
]
}Note que a resposta de recibos não tem erros[] - falhas por competência são registradas em log e não abortam a coleta das demais. Se nenhum CNPJ for resolvido, retorna 422 com "Informe 'contribuinte.numero' (CNPJ), ou 'cnpjs', ou 'usar_lista_interna=true' com customer_service válido.". Erro global retorna 500 com message: "Erro ao coletar recibos".
Escopo: dctfweb:write
POST /dctfweb/emissao/recibos/baixar-mensal
Coleta/lista os recibos de uma única competência, para 1 CNPJ ou toda a carteira interna.
Parâmetros
Sem parâmetros de rota ou query - corpo em RecibosMensalRequest: contribuinte ou usar_lista_interna: true, e a competência via competencia ("AAAA-MM") ou o par ano + mes.
Request
{
"contribuinte": { "tipo": 2, "numero": "27898481000150" },
"competencia": "2025-06"
}Alternativa - competência via ano + mes:
{
"contribuinte": { "tipo": 2, "numero": "27898481000150" },
"ano": 2025,
"mes": 6
}Response 200 OK
Mesmo envelope { summary, recibos } do baixar-todas, restrito à competência informada.
Competência mal formada retorna 422 ("Formato de 'competencia' inválido. Use 'YYYY-MM'."); ausência de competência e de ano/mes válidos retorna 422 ("Informe 'competencia' (YYYY-MM) ou 'ano' e 'mes' válidos."). Erro global retorna 500 com message: "Erro ao coletar recibos mensais".
Ao coletar, registra uma atividade de auditoria por cliente (no modo usar_lista_interna, apenas para CNPJs de matriz, contendo 0001).
Escopo: dctfweb:write
Integração com o Serpro (Integra Contador)
As rotas orquestram as seguintes chamadas ao Integra Contador por CNPJ/competência:
| Serviço | Papel |
|---|---|
DCTFWeb - CONSRECIBO32 | Obtém o numeroReciboEntrega da transmissão; usado na emissão do DARF e no download do recibo. |
DCTFWeb - GERARGUIA31 | Emite a guia DCTFWeb. Em emitir, categoria e idsSistemaOrigem vêm do corpo; nas rotas baixar-mensal/*, são GERAL_MENSAL + [1, 6, 7] (eSocial) ou [8] (MIT), literais no código. |
PGDAS-D - pgdasd_gerar_das | Emite o DAS do Simples Nacional para o periodoApuracao (AAAAMM). Só nas rotas de coleta em lote. |
| PGDAS-D - extrato do DAS | Fallback: recupera PDF, linha digitável e vencimento quando o DAS não vem inline. |
Nas rotas de coleta, todas as chamadas usam contribuinte = { tipo: 2, numero: <CNPJ> } (pessoa jurídica). Em emitir, o tipo é derivado do comprimento do documento (2 para CNPJ, 1 para CPF), porque as categorias PF_MENSAL e PF_13o_SALARIO são de pessoa física empregadora.
Os PDFs em base64 devolvidos pelo Serpro são decodificados e salvos em disco pelas rotas de coleta; o caminho fica em extras.pdfGuiaPath (guia DCTFWeb), extras.pdfPath (PGDAS-D) ou pdfPath (recibo). Em emitir, o PDF é gravado no registro de Guias e sai por GET /dctfweb/guias/{guia_id}/pdf.
`idsSistemaOrigem` é fixo nas rotas `baixar-mensal/*`
As variantes esocial e mit diferem apenas pelo idsSistemaOrigem enviado ao Serpro, que é literal no código - não é um parâmetro do corpo, e o schema delas sequer declara o campo. Quem precisa escolher as origens usa POST /dctfweb/emissao/guias/emitir.
O catálogo dos códigos aceitos e o que cada um traz para a guia estão em DCTFWeb: Catálogos.
Schemas
DctfwebEmitirGuiaRequest
Corpo de POST /dctfweb/emissao/guias/emitir. Rejeita campos desconhecidos (extra="forbid"): um nome digitado errado vira 422, e não uma emissão silenciosa com o parâmetro ignorado.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
cnpj | str (11-20) | sim | CNPJ/CPF do contribuinte, com ou sem máscara. Precisa pertencer a um cliente do escritório. |
anoPA | str | sim | Ano de apuração, string de 4 dígitos: "2026". Padrão ^\d{4}$. |
mesPA | str | condicional | Mês com zero à esquerda: "04". Padrão ^(0[1-9]|1[0-2])$. Obrigatório em todas as categorias exceto as de 13º. |
categoria | DCTFCategoria | não | Default GERAL_MENSAL. Aceita o rótulo ("GERAL_MENSAL"), não o código numérico. |
idsSistemaOrigem | List[int] | não | Origens das receitas. Omitir ≠ [] - ver o aviso acima. Inteiros estritos, sem repetição, dentro de 1, 5, 6, 7, 8. |
numeroReciboEntrega | str (≤60) | não | Recibo da declaração alvo. Normalmente dispensável; informe no cenário MG10. |
diaPA | str | condicional | Somente em ESPETACULO_DESPORTIVO (e obrigatório lá). Padrão ^(0[1-9]|[12][0-9]|3[01])$. |
cnoAfericao | int (≥0) | condicional | Somente em AFERICAO (e obrigatório lá). Número da obra (CNO), numérico. |
numProcReclamatoria | str (≤60) | condicional | Somente em RECLAMATORIA_TRABALHISTA (e obrigatório lá). |
As regras condicionais valem nos dois sentidos: o campo é obrigatório na categoria dona e recusado em todas as outras ("'cnoAfericao' só se aplica à categoria AFERICAO."). mesPA enviado numa categoria de 13º também é 422, porque a declaração é anual. A tabela completa está em DCTFWeb: Catálogos.
`anoPA` e `mesPA` são STRING nesta rota
Não presuma simetria com as rotas de lote, que aceitam ano/mes inteiros: aqui os campos seguem o contrato da DCTFWeb e são texto com zero à esquerda. {"anoPA": 2026} e {"mesPA": 4} são 422; o correto é {"anoPA": "2026", "mesPA": "04"}.
O mesmo vale para categoria: o valor é o rótulo ("GERAL_MENSAL", "AFERICAO", ...), não o código numérico da tabela (40, 44, ...).
DctfwebEmissaoGuiaResultado
Conteúdo de data na resposta de POST /dctfweb/emissao/guias/emitir.
| Campo | Tipo | Observações |
|---|---|---|
id_guia | int | null | Id no registro de Guias - o elo para baixar o PDF. null só se a persistência falhar. |
id_cliente | int | Id do cliente resolvido a partir do cnpj. |
cnpj | str | CNPJ normalizado (só dígitos), mesmo que tenha entrado mascarado. |
categoria | str | Rótulo da categoria efetivamente usada. |
competencia | str | "AAAA-MM" - ou "AAAA" nas categorias de 13º, que são anuais. Nenhum mês sintético é inventado. |
idsSistemaOrigem | List[int] | null | O que foi efetivamente enviado à Receita. null = campo omitido (guia com todas as receitas). |
setor | str | fiscal | pessoal. Derivado das origens - ver o aviso acima. |
numero_recibo | str | null | Recibo usado para identificar a declaração. null quando não foi informado nem obtido. |
arquivo_nome | str | null | dctfweb_guia_<cnpj>_<competencia>.pdf. null quando não houve PDF. |
tem_pdf | bool | A Receita devolveu o PDF nesta emissão? Leia antes de oferecer download. |
mensagem | str | Desfecho em pt-BR. |
GuiasDownloadRequest
Corpo das três rotas de guias.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
contribuinte | ParteIdentificacao | condicional | CNPJ único. |
usar_lista_interna | bool | não | Default false. Se true, coleta para toda a carteira interna. |
anos | int (1-3) | não | Default 1. Usado apenas em baixar-todas. |
competencia | str | condicional | Competência "AAAA-MM". Usada nas rotas baixar-mensal/*. |
ano | int | condicional | Alternativa a competencia (par com mes) nas rotas mensais. |
mes | int | condicional | Alternativa a competencia (par com ano) nas rotas mensais. |
O alvo deve vir por contribuinte.numero ou usar_lista_interna=true.
RecibosDownloadRequest
Corpo de POST /dctfweb/emissao/recibos/baixar-todas.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
contribuinte | ParteIdentificacao | condicional | CNPJ único. |
usar_lista_interna | bool | não | Default false. |
anos | int (1-3) | não | Anos retroativos a percorrer. Default 1. |
RecibosMensalRequest
Corpo de POST /dctfweb/emissao/recibos/baixar-mensal.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
contribuinte | ParteIdentificacao | condicional | CNPJ único. |
usar_lista_interna | bool | não | Default false. |
competencia | str | condicional | Formato AAAA-MM (validado por regex ^\d{4}-(0[1-9]|1[0-2])$). |
ano | int | condicional | Usado quando competencia não é informada. |
mes | int | condicional | Usado quando competencia não é informada. |
dir_saida | str | não | Diretório de saída dos PDFs. |
ParteIdentificacao
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
tipo | int | sim | 1 = PF (CPF), 2 = PJ (CNPJ). Estas rotas usam 2. |
numero | str | sim | CPF/CNPJ, preferencialmente só dígitos. |
GuiasDownloadResponse
| Campo | Tipo | Observações |
|---|---|---|
summary | GuiasSummary | Resumo agregado da coleta. |
guias | List[Guia] | Guias emitidas/coletadas. |
erros | List[GuiaErro] | Falhas por CNPJ/competência. Default []. |
GuiasSummary
| Campo | Tipo | Observações |
|---|---|---|
total | int | Total de guias coletadas. |
abertas | int | Default 0 - o status não é resolvido nesta coleta. |
pagas | int | Default 0. |
vencidas | int | Default 0. |
porTipo | Dict[str, int] | Contagem por tipo (DCTF, PGDAS, ...). |
Estes são todos os campos declarados no response_model: qualquer chave extra produzida internamente é descartada na serialização e não chega ao cliente.
Guia
| Campo | Tipo | Observações |
|---|---|---|
id | str | Ex.: DCTFWeb:<cnpj>:<competencia>. |
tipo | str | DAS, DCTF, DARF, GPS, etc. |
competencia | str | AAAA-MM. |
valor | float | Default 0.0 - a DCTFWeb não resolve valor nesta coleta. |
dataVencimento | str | null | Vencimento, quando disponível. |
status | str | aberta | paga | vencida | desconhecida (default). |
clienteNumero | str | CNPJ do cliente (somente dígitos). |
clienteNome | str | null | Nome do cliente, quando disponível. |
descricao | str | null | Descrição legível. |
codigoBarras | str | null | Linha digitável / código de barras (PGDAS-D). |
dataGeracao | str | null | AAAA-MM-DD. |
observacoes | str | null | - |
origem | str | DCTFWeb, PGDAS-D, etc. |
extras | Dict[str, Any] | Payload cru do Serpro e caminhos de PDF (pdfGuiaPath / pdfPath, numeroDas). |
GuiaErro
| Campo | Tipo | Observações |
|---|---|---|
cnpj | str | CNPJ que falhou. |
status | int | null | Código HTTP da falha do Serpro, quando houver. |
detail | str | Descrição do erro. |
RecibosDownloadResponse
| Campo | Tipo | Observações |
|---|---|---|
summary | RecibosSummary | Resumo agregado da coleta. |
recibos | List[Recibo] | Recibos coletados (pode vir vazio). |
Não há erros[] nesta resposta.
RecibosSummary
O shape é idêntico ao de GuiasSummary, por compatibilidade. Para recibos, os campos de situação de pagamento (abertas, pagas, vencidas) ficam sempre em 0.
Recibo
| Campo | Tipo | Observações |
|---|---|---|
id | str | origem:cnpj:AAAA-MM. |
tipo | str | DCTF | PGDAS. |
competencia | str | AAAA-MM. |
clienteNumero | str | CNPJ do cliente (somente dígitos). |
descricao | str | null | Ex.: Recibo DCTFWeb - 2025-06. |
origem | str | DCTFWeb ou PGDAS-D. |
dataGeracao | str | null | AAAA-MM-DD. |
pdfPath | str | null | Caminho do PDF salvo; null quando o Serpro não retorna PDF válido. |
extras | Dict[str, Any] | Metadados; inclui consulta com a resposta bruta do Serpro. |
Notas
- As seis rotas são
POSTe exigemdctfweb:write- sem exigência de perfil, e API Key é aceita (diferente da Transmissão). - Envelope: as cinco rotas
baixar-*devolvem o objeto direto (response_model), não{ status, message, data };emitirusa o envelope padrão. - Em
emitir, omitiridsSistemaOrigem≠ enviar[]: omitido gera a guia com todas as receitas;[]é422. E a tipagem é estrita -"1"etruenão são coeridos para1. - Em
emitir, a resposta não traz o PDF: useid_guia+GET /dctfweb/guias/{guia_id}/pdf. Chequetem_pdfantes. - Em
emitir,setoré derivado (fiscalsó quando as origens são exatamente[8]); persistência da guia e registro de atividade são best-effort e não derrubam uma emissão que já ocorreu na Receita. - A coleta em lote é síncrona e percorre CNPJ × competência sequencialmente. Prefira
contribuintepara respostas rápidas e reserveusar_lista_internapara lotes. - A diferença entre
baixar-mensal/esocialebaixar-mensal/mité apenas oidsSistemaOrigemna emissão da DCTFWeb. - A coleta de PGDAS-D nos recibos está implementada no serviço mas desativada no fluxo atual; as respostas de recibo trazem apenas origem
DCTFWeb. - Quando o Serpro sinaliza que não há débitos com saldo a pagar, a competência é reportada como erro
422naquele item, sem abortar a coleta. baixar-todaslimitaanosa no máximo3.