DCTFWeb: Guias
Endpoints da WebApiAlcance para o registro interno das guias de DCTFWeb e PGDAS emitidas pela plataforma. Este domínio não fala com o Serpro: ele guarda, lista e serve o que já foi emitido - metadados (cliente, usuário, setor, tipo, competência, status) e o PDF da guia.
Quem emite é o domínio de Emissão, que grava aqui cada guia coletada. Registros também podem nascer pelo CRUD, fora do fluxo da automação.
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 (tag DCTFWeb: Guias).
Caminho antigo `/dctfweb-guias` continua vivo, porém deprecado
Cada rota desta página tem um alias em /api/v1/dctfweb-guias/... que serve o mesmo handler - migrar não muda requisição nem resposta. O alias exige os escopos antigos (dctfweb_guias:read / dctfweb_guias:write) e será removido numa versão futura. Mapa rota a rota em DCTFWeb: visão geral.
Base path
/api/v1/dctfweb/guiasEscopos necessários
dctfweb:read- listagem, consulta por ID e download do PDF (rotasGET).dctfweb:write- criação, atualização e remoção (POST,PUT,DELETE).
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 esses escopos - relogue ou atualize a API Key antes de migrar.
Envelope de resposta
Exceto o download de PDF (que devolve bytes), toda resposta segue o envelope padrão da WebApi:
{
"status": "success",
"message": "Mensagem em PT-BR",
"data": {}
}Endpoints
POST /dctfweb/guias/
Registra uma nova guia de DCTFWeb/PGDAS. Responde 201 Created.
Parâmetros
Sem parâmetros de rota ou query - os dados vão no corpo da requisição (DctfwebGuiaCreate, ver DctfwebGuiaCreate).
Autoria não é forjável
O campo id_usuario do corpo é sobrescrito pelo usuário autenticado antes da gravação. Enviá-lo com outro valor não tem efeito.
Request
{
"id_cliente": 123,
"id_usuario": 7,
"setor": "pessoal",
"tipo": "DCTFWeb",
"competencia": "2025-06",
"status": "Concluído",
"arquivo_nome": "DCTFWeb_27898481000150_2025-06.pdf",
"arquivo_mime": "application/pdf",
"file_base64": "JVBERi0xLjQK..."
}Response 201 Created
{
"status": "success",
"message": "Guia registrada com sucesso!",
"data": {
"id": 4210,
"id_cliente": 123,
"id_usuario": 7,
"atividade_id": null,
"data_hora_emissao": "2026-08-05T09:12:44-03:00",
"setor": "pessoal",
"tipo": "DCTFWeb",
"competencia": "2025-06",
"status": "Concluído",
"arquivo_nome": "DCTFWeb_27898481000150_2025-06.pdf",
"arquivo_mime": "application/pdf"
}
}O data segue DctfwebGuiaRead e nunca inclui file_base64.
Escopo: dctfweb:write
GET /dctfweb/guias/
Lista guias no envelope paginado, com filtros e ordenação. O campo file_base64 não é retornado - para o PDF use GET /dctfweb/guias/{guia_id}/pdf.
Parâmetros de query
| Parâmetro | Tipo | Default | Observações |
|---|---|---|---|
id_cliente | int | - | Filtra por cliente. |
id_usuario | int | - | Filtra por usuário (autoria). |
setor | str | - | fiscal | pessoal. Case-insensitive, ignora espaços nas pontas. |
tipo | str | - | DCTFWeb | PGDAS. Case-insensitive. |
status | str | - | Ex.: Concluído, Falha. Case-insensitive. |
competencia | str | - | Competência AAAA-MM. |
start_date | datetime | - | data_hora_emissao >= start_date. |
end_date | datetime | - | data_hora_emissao <= end_date. |
sort_by | str (whitelist) | data_hora_emissao | Whitelist na seção Ordenação, abaixo. Valor fora dela → 422. |
sort_dir | asc | desc | desc | Valor fora da whitelist → 422. |
page | int (≥ 1) | 1 | Página, 1-based. |
per_page | int (1-500) | - | Itens por página. Se omitido, retorna todos (sem paginar). |
Request
GET /api/v1/dctfweb/guias/?setor=pessoal&competencia=2025-06&page=1&per_page=20Response 200 OK
{
"status": "success",
"message": "Guias recuperadas com sucesso!",
"data": {
"items": [
{
"id": 4210,
"id_cliente": 123,
"id_usuario": 7,
"atividade_id": 9981,
"data_hora_emissao": "2026-08-05T09:12:44-03:00",
"setor": "pessoal",
"tipo": "DCTFWeb",
"competencia": "2025-06",
"status": "Concluído",
"arquivo_nome": "DCTFWeb_27898481000150_2025-06.pdf"
}
],
"total": 137,
"total_pages": 7,
"current_page": 1,
"per_page": 20
}
}Quando per_page é omitido, total_pages vale 1 e per_page vem null.
Escopo: dctfweb:read
GET /dctfweb/guias/{guia_id}
Busca uma guia pelo ID. Retorna apenas metadados (DctfwebGuiaRead), sem file_base64.
Parâmetros
| Parâmetro | Local | Tipo | Obrigatório | Observações |
|---|---|---|---|---|
guia_id | rota | int | sim | ID da guia. |
Response 200 OK
{
"status": "success",
"message": "Guia encontrada com sucesso!",
"data": {
"id": 4210,
"id_cliente": 123,
"id_usuario": 7,
"atividade_id": 9981,
"data_hora_emissao": "2026-08-05T09:12:44-03:00",
"setor": "pessoal",
"tipo": "DCTFWeb",
"competencia": "2025-06",
"status": "Concluído",
"arquivo_nome": "DCTFWeb_27898481000150_2025-06.pdf",
"arquivo_mime": "application/pdf"
}
}ID inexistente retorna 404 com detail: "Guia de DCTFWeb com ID {id} não encontrada!".
Escopo: dctfweb:read
PUT /dctfweb/guias/{guia_id}
Atualiza uma guia. Todos os campos do corpo são opcionais - só os informados são aplicados.
Parâmetros
guia_id na rota; corpo em DctfwebGuiaUpdate (ver DctfwebGuiaUpdate).
Campos deliberadamente não editáveis
id_cliente, id_usuario e data_hora_emissao não existem no corpo de atualização. O PUT não pode reatribuir a guia a outro cliente/usuário nem reescrever a data de emissão.
Request
{
"status": "Falha",
"competencia": "2025-07"
}Response 200 OK
{
"status": "success",
"message": "Guia atualizada com sucesso!",
"data": {
"id": 4210,
"id_cliente": 123,
"id_usuario": 7,
"atividade_id": 9981,
"data_hora_emissao": "2026-08-05T09:12:44-03:00",
"setor": "pessoal",
"tipo": "DCTFWeb",
"competencia": "2025-07",
"status": "Falha",
"arquivo_nome": "DCTFWeb_27898481000150_2025-06.pdf",
"arquivo_mime": "application/pdf"
}
}ID inexistente retorna 404.
Escopo: dctfweb:write
DELETE /dctfweb/guias/{guia_id}
Remove uma guia pelo ID.
Restrito por perfil
Além do escopo dctfweb:write, esta rota exige perfil administrador ou diretoria. Um token com o escopo correto mas perfil operacional é recusado.
Response 200 OK
{
"status": "success",
"message": "Guia deletada com sucesso!",
"data": null
}ID inexistente retorna 404.
Escopo: dctfweb:write + perfil administrador ou diretoria
GET /dctfweb/guias/{guia_id}/pdf
Devolve o PDF binário da guia - esta é a única rota que expõe o arquivo.
Response 200 OK
Content-Type: application/pdfContent-Disposition: attachment; filename="<nome ASCII>"; filename*=UTF-8''<nome real>
O nome usa arquivo_nome do registro; quando ausente, cai para dctfweb_guia_{id}.pdf. O cabeçalho traz as duas formas (RFC 6266): filename* carrega o nome real em UTF-8 e filename= é o fallback ASCII para clientes antigos.
Retorna 404 quando não há registro, quando não há PDF gravado, ou quando o base64 armazenado não pôde ser decodificado - neste último caso com detail: "PDF da guia com ID {id} não pôde ser decodificado!".
Sem envelope
Diferente das demais rotas, esta não responde { status, message, data } - o corpo é o PDF. Erros aqui saem como HTTPException ({ "detail": "..." }), com o status HTTP real.
Escopo: dctfweb:read
Ordenação
sort_by aceita apenas os valores abaixo (validados por Literal; qualquer outro retorna 422):
sort_by | Ordena por |
|---|---|
data_hora_emissao | Data/hora de emissão. Default. |
cliente | Nome do cliente (customer.razao_social), não o ID. |
usuario | Nome do usuário (user.nome), não o ID. |
status | Status do registro. |
setor | Setor (fiscal / pessoal). |
tipo | Tipo (DCTFWeb / PGDAS). |
competencia | Competência AAAA-MM. |
sort_dir aceita asc ou desc (default desc). O desempate é sempre por id, na mesma direção do sort primário - as guias de um mesmo lote compartilham o mesmo data_hora_emissao, e sem o desempate a paginação repetiria ou pularia registros entre páginas.
Schemas
DctfwebGuiaCreate
Corpo de POST /dctfweb/guias/.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
id_cliente | int | sim | FK do cliente. |
id_usuario | int | sim | Ignorado: sobrescrito pelo usuário autenticado. |
atividade_id | int | null | não | Atividade que originou a guia. Nulo quando o registro nasce pelo CRUD. |
setor | "fiscal" | "pessoal" | sim | Valor fora do par → 422. |
tipo | "DCTFWeb" | "PGDAS" | sim | Valor fora do par → 422. |
competencia | str (≤ 20) | não | Competência AAAA-MM. |
status | str (≤ 50) | sim | Ex.: Concluído, Falha. |
arquivo_nome | str (≤ 255) | não | Nome do arquivo, usado no Content-Disposition do download. |
arquivo_mime | str (≤ 100) | não | Normalmente application/pdf. |
file_base64 | str | null | não | PDF em base64. Só entra na escrita - nenhum schema de leitura o expõe. |
data_hora_emissao | datetime | null | não | Quando nulo, o banco resolve com o instante do INSERT. |
DctfwebGuiaUpdate
Corpo de PUT /dctfweb/guias/{guia_id}. Todos os campos são opcionais.
| Campo | Tipo | Observações |
|---|---|---|
setor | "fiscal" | "pessoal" | - |
tipo | "DCTFWeb" | "PGDAS" | - |
competencia | str (≤ 20) | - |
status | str (≤ 50) | - |
file_base64 | str | Substitui o PDF gravado. |
arquivo_nome | str (≤ 255) | - |
arquivo_mime | str (≤ 100) | - |
id_cliente, id_usuario e data_hora_emissao não fazem parte deste schema.
DctfwebGuiaRead
data de POST, GET /{guia_id} e PUT.
| Campo | Tipo | Observações |
|---|---|---|
id | int | ID da guia. |
id_cliente | int | - |
id_usuario | int | Autor do registro. |
atividade_id | int | null | - |
data_hora_emissao | datetime | null | - |
setor | str | fiscal | pessoal. |
tipo | str | DCTFWeb | PGDAS. |
competencia | str | null | AAAA-MM. |
status | str | - |
arquivo_nome | str | null | - |
arquivo_mime | str | null | - |
Não inclui file_base64.
DctfwebGuiaListItem
Item de items[] na listagem. Igual ao DctfwebGuiaRead, sem arquivo_mime e sem file_base64.
PaginatedDctfwebGuias
data de GET /dctfweb/guias/.
| Campo | Tipo | Observações |
|---|---|---|
items | List[DctfwebGuiaListItem] | Página atual. |
total | int | Total de registros que atendem aos filtros. |
total_pages | int | 1 quando per_page é omitido. |
current_page | int | Ecoa o page recebido. |
per_page | int | null | null quando omitido na requisição (retorno sem paginação). |
Notas
- O PDF fica em coluna
MEDIUMTEXT(até 16 MB) e nunca aparece nas respostas JSON - só emGET /{guia_id}/pdf. - Os filtros
setor,tipoestatuscomparam em maiúsculas e sem espaços nas pontas, dos dois lados. sort_by=clienteesort_by=usuariofazemJOINe ordenam pelo nome, que é o que o consumidor exibe.- Apagar a atividade que originou a guia não apaga a guia:
atividade_idficanull(o PDF pode ser a única cópia do artefato). - Alias deprecado equivalente:
/api/v1/dctfweb-guias/...(escoposdctfweb_guias:read/dctfweb_guias:write).