Smart: Impostos Retidos

Endpoints da WebApiAlcance para os impostos retidos na fonte exportados do produto Smart. O domínio reúne quatro relatórios de origem (ir_pcc_inss, terceiros_pj, iss, servicos_tomados) numa única tabela, discriminados pelo campo tipo_relatorio - eles são quatro recortes do mesmo fato (um pagamento a fornecedor com tributo retido), então toda soma/apuração deve filtrar por tipo_relatorio, sob risco de contar a mesma retenção mais de uma vez. Diferente do restante da família Smart, este domínio tem chave natural (10 colunas) e uma rota de importação em lote idempotente, além do CRUD unitário padrã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.

Base path

/api/v1/smart-impostos-retidos

Escopos necessários

  • smart_impostos_retidos:read - listagem e busca por ID
  • smart_impostos_retidos:write - importação em lote, criação avulsa, atualização e exclusão

O escopo é derivado do prefixo público da rota: /smart-impostos-retidos vira o recurso smart_impostos_retidos (hífen → underscore), e o método HTTP define a ação (read para GET, write para POST/PUT/DELETE). Os quatro relatórios de origem compartilham o mesmo prefixo e, portanto, os mesmos 2 escopos - eles não são domínios separados.

Ordem das rotas

A rota literal POST /smart-impostos-retidos/importar é declarada antes das rotas com parâmetro de path para que nenhuma delas a capture. Ela não cria um escopo próprio: continua exigindo smart_impostos_retidos:write.

Endpoints

POST /smart-impostos-retidos/importar

Importa uma planilha inteira em uma única requisição, de forma idempotente: reimportar o mesmo lote não cria linhas novas (upsert pela chave natural). Em conflito, atualiza apenas as colunas não-chave - id e data_hora_criacao são preservados. Erros de validação de negócio recusam o lote inteiro (nunca sucesso parcial).

Parâmetros

Este endpoint não recebe parâmetros de rota ou query. O corpo é um ImportacaoLoteRequest.

Request

{
  "tipo_relatorio": "ir_pcc_inss",
  "cnpj": "12345678000199",
  "itens": [
    {
      "emp_cgc": "98765432000188",
      "cpg_credor": "FORNECEDOR EXEMPLO LTDA",
      "cpg_serie": "1",
      "cpg_num": 7788,
      "cpg_doc": "7788",
      "cpg_dt_doc_emiss": "2026-04-01T00:00:00",
      "ipg_parc": 1,
      "total_parc": 1,
      "ipg_valor": 5000.0,
      "valor_emissao": 5000.0,
      "ipg_irrf": 75.0,
      "ipg_inss": 550.0,
      "indic": "IRRF",
      "ipg_dt_pgto": "2026-04-10T00:00:00",
      "mcc_irrf": 75.0,
      "mcc_inss": 550.0
    }
  ]
}

Response 200 OK

{
  "status": "success",
  "message": "Importação concluída",
  "data": {
    "total": 1,
    "criados": 1,
    "atualizados": 0,
    "duplicados_no_lote": 0,
    "avisos": []
  }
}

Erros de validação (ex.: colunas mcc_* divergentes das ipg_* correspondentes, itens com a mesma chave natural e payloads diferentes, falha de persistência) respondem {"message": "<texto>"} com 422 Unprocessable Entity e nada é gravado.

Escopo: smart_impostos_retidos:write

GET /smart-impostos-retidos/

Lista os impostos retidos, com filtro opcional por CNPJ e por tipo_relatorio, e paginação.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
cnpjstringquerynãoFiltra por CNPJ do cliente.
tipo_relatoriostringquerynãoFiltra pelo pivot de origem: ir_pcc_inss, terceiros_pj, iss ou servicos_tomados. Recomendado em toda soma/apuração.
limitintquerynãoItens por página. 1..500. Default 100.
offsetintquerynãoOffset de paginação. >= 0. Default 0.

Request

Sem corpo de requisição.

Response 200 OK

{
  "status": "success",
  "message": "Impostos retidos recuperados com sucesso",
  "data": [
    {
      "id": 4102,
      "tipo_relatorio": "ir_pcc_inss",
      "cnpj": "12345678000199",
      "cfg_emp": "01 - HOSPITAL EXEMPLO",
      "gcc_descr": "FORNECEDORES DIVERSOS",
      "cde_nome": "FORNECEDOR EXEMPLO LTDA",
      "emp_cgc": "98765432000188",
      "cpg_credor": "FORNECEDOR EXEMPLO LTDA",
      "cpg_serie": "1",
      "cpg_num": 7788,
      "cpg_doc": "7788",
      "cpg_dt_doc_emiss": "2026-04-01T00:00:00",
      "ipg_parc": 1,
      "total_parc": 1,
      "ipg_valor": 5000.0,
      "valor_emissao": 5000.0,
      "valor_pagamento": 5000.0,
      "valor_bruto": null,
      "ipg_irrf": 75.0,
      "ipg_inss": 550.0,
      "ipg_iss": 0.0,
      "ipg_imp_pis": 32.5,
      "ipg_imp_cofins": 150.0,
      "ipg_imp_cssl": 50.0,
      "indic": "IRRF",
      "indic_1": "SERV",
      "indic_2": "Titulos",
      "fis_jur": "J",
      "cfo": "6.202",
      "conta_contabil": "2.1.3.01.001",
      "banco": "BANCO EXEMPLO",
      "ipg_dt_pgto": "2026-04-10T00:00:00",
      "data_hora_criacao": "2026-04-11T08:00:00"
    }
  ]
}

Se nenhum registro casar com o filtro, data volta [] com 200 OK e message: "Nenhum imposto retido encontrado.".

Escopo: smart_impostos_retidos:read

GET /smart-impostos-retidos/{registro_id}

Busca um imposto retido pelo ID.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
registro_idintpathsimID do imposto retido.

Request

Sem corpo de requisição.

Response 200 OK

{
  "status": "success",
  "message": "Imposto retido recuperado com sucesso",
  "data": {
    "id": 4102,
    "tipo_relatorio": "ir_pcc_inss",
    "cnpj": "12345678000199",
    "cfg_emp": "01 - HOSPITAL EXEMPLO",
    "gcc_descr": "FORNECEDORES DIVERSOS",
    "cde_nome": "FORNECEDOR EXEMPLO LTDA",
    "emp_cgc": "98765432000188",
    "cpg_credor": "FORNECEDOR EXEMPLO LTDA",
    "cpg_serie": "1",
    "cpg_num": 7788,
    "cpg_doc": "7788",
    "cpg_dt_doc_emiss": "2026-04-01T00:00:00",
    "ipg_parc": 1,
    "total_parc": 1,
    "ipg_valor": 5000.0,
    "valor_emissao": 5000.0,
    "valor_pagamento": 5000.0,
    "valor_bruto": null,
    "ipg_irrf": 75.0,
    "ipg_inss": 550.0,
    "ipg_iss": 0.0,
    "ipg_imp_pis": 32.5,
    "ipg_imp_cofins": 150.0,
    "ipg_imp_cssl": 50.0,
    "indic": "IRRF",
    "indic_1": "SERV",
    "indic_2": "Titulos",
    "fis_jur": "J",
    "cfo": "6.202",
    "conta_contabil": "2.1.3.01.001",
    "banco": "BANCO EXEMPLO",
    "ipg_dt_pgto": "2026-04-10T00:00:00",
    "data_hora_criacao": "2026-04-11T08:00:00"
  }
}

Quando o ID não existe, responde {"message": "Imposto retido não encontrado."} com 404 Not Found.

Escopo: smart_impostos_retidos:read

POST /smart-impostos-retidos/

Cria um registro avulso (correção pontual - a carga em massa é POST /smart-impostos-retidos/importar).

Parâmetros

Este endpoint não recebe parâmetros de rota ou query. O corpo é um SmartImpostosRetidosCreate.

Request

{
  "tipo_relatorio": "ir_pcc_inss",
  "cnpj": "12345678000199",
  "emp_cgc": "98765432000188",
  "cpg_credor": "FORNECEDOR EXEMPLO LTDA",
  "cpg_serie": "1",
  "cpg_num": 7788,
  "cpg_doc": "7788",
  "cpg_dt_doc_emiss": "2026-04-01T00:00:00",
  "ipg_parc": 1,
  "total_parc": 1,
  "ipg_valor": 5000.0,
  "valor_emissao": 5000.0,
  "ipg_irrf": 75.0,
  "ipg_inss": 550.0,
  "indic": "IRRF",
  "ipg_dt_pgto": "2026-04-10T00:00:00"
}

Response 201 Created

{
  "status": "success",
  "message": "Imposto retido criado com sucesso",
  "data": {
    "id": 4102,
    "tipo_relatorio": "ir_pcc_inss",
    "cnpj": "12345678000199",
    "emp_cgc": "98765432000188",
    "cpg_credor": "FORNECEDOR EXEMPLO LTDA",
    "cpg_serie": "1",
    "cpg_num": 7788,
    "cpg_doc": "7788",
    "cpg_dt_doc_emiss": "2026-04-01T00:00:00",
    "ipg_parc": 1,
    "total_parc": 1,
    "ipg_valor": 5000.0,
    "valor_emissao": 5000.0,
    "valor_pagamento": null,
    "valor_bruto": null,
    "ipg_irrf": 75.0,
    "ipg_inss": 550.0,
    "ipg_iss": null,
    "ipg_imp_pis": null,
    "ipg_imp_cofins": null,
    "ipg_imp_cssl": null,
    "indic": "IRRF",
    "indic_1": null,
    "indic_2": null,
    "fis_jur": null,
    "cfo": null,
    "conta_contabil": null,
    "banco": null,
    "ipg_dt_pgto": "2026-04-10T00:00:00",
    "data_hora_criacao": "2026-04-11T08:00:00"
  }
}

Como a tabela tem chave natural, um POST repetido com os mesmos 10 campos-chave responde {"message": "<texto>"} com 409 Conflict.

Escopo: smart_impostos_retidos:write

PUT /smart-impostos-retidos/{registro_id}

Atualiza um imposto retido (update parcial). Não aceita nenhum dos 10 campos da chave natural (ver SmartImpostosRetidosUpdate) - mover um registro de tenant/pivot por HTTP não é permitido.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
registro_idintpathsimID do imposto retido.

O corpo é um SmartImpostosRetidosUpdate.

Request

{ "ipg_valor": 5200.0, "ipg_irrf": 78.0 }

Response 200 OK

{
  "status": "success",
  "message": "Imposto retido atualizado com sucesso",
  "data": {
    "id": 4102,
    "tipo_relatorio": "ir_pcc_inss",
    "cnpj": "12345678000199",
    "emp_cgc": "98765432000188",
    "cpg_credor": "FORNECEDOR EXEMPLO LTDA",
    "cpg_serie": "1",
    "cpg_num": 7788,
    "cpg_doc": "7788",
    "cpg_dt_doc_emiss": "2026-04-01T00:00:00",
    "ipg_parc": 1,
    "total_parc": 1,
    "ipg_valor": 5200.0,
    "valor_emissao": 5000.0,
    "valor_pagamento": null,
    "valor_bruto": null,
    "ipg_irrf": 78.0,
    "ipg_inss": 550.0,
    "ipg_iss": null,
    "ipg_imp_pis": null,
    "ipg_imp_cofins": null,
    "ipg_imp_cssl": null,
    "indic": "IRRF",
    "indic_1": null,
    "indic_2": null,
    "fis_jur": null,
    "cfo": null,
    "conta_contabil": null,
    "banco": null,
    "ipg_dt_pgto": "2026-04-10T00:00:00",
    "data_hora_criacao": "2026-04-11T08:00:00"
  }
}

Quando o ID não existe, responde {"message": "Imposto retido não encontrado."} com 404 Not Found.

Escopo: smart_impostos_retidos:write

DELETE /smart-impostos-retidos/{registro_id}

Remove um imposto retido.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
registro_idintpathsimID do imposto retido.

Request

Sem corpo de requisição.

Response 200 OK

{
  "status": "success",
  "message": "Imposto retido removido com sucesso",
  "data": null
}

Quando o ID não existe, responde {"message": "Imposto retido não encontrado."} com 404 Not Found.

Escopo: smart_impostos_retidos:write

Schemas

Vocabulário tipo_relatorio

ValorOrigem
ir_pcc_inss1 linha por parcela x grupo de tributo (indic).
terceiros_pj1 linha por parcela.
iss1 linha por parcela.
servicos_tomados1 linha por documento (sem série/número/parcela).

SmartImpostosRetidosCreate

Corpo do POST /smart-impostos-retidos/. model_config usa extra="forbid": qualquer campo fora desta lista responde 422.

CampoTipoObrigatórioObservações
tipo_relatoriostringsimUm dos 4 valores do vocabulário acima.
ipg_dt_pgtodatetimesimData do pagamento. Parte da chave natural.
cnpjstringnãoMáx. 30. CNPJ do cliente (quem paga); normalizado pela API.
cfg_empstringnãoMáx. 300. Identificação da empresa na origem.
gcc_descrstringnãoMáx. 300. Descrição do grupo/conta contábil de origem.
cde_nomestringnãoMáx. 300. Nome de referência do credor na origem.
emp_cgcstringnãoMáx. 30. CNPJ do credor/fornecedor (quem recebe); gravado como veio, sem normalização.
cpg_credorstringnãoMáx. 300. Nome do credor/fornecedor.
cpg_seriestringnãoMáx. 20. Série do documento de pagamento. Parte da chave natural.
cpg_numintnãoNúmero do documento de pagamento. Parte da chave natural.
cpg_docstringnãoMáx. 20. Identificador do documento na origem (número, data DDMMAAAA ou competência MM/AAAA, conforme o relatório). Parte da chave natural.
cpg_dt_doc_emissdatetimenãoData de emissão do documento. Parte da chave natural.
ipg_parcintnãoNúmero da parcela. Parte da chave natural.
total_parcintnãoTotal de parcelas do documento.
ipg_valorDecimalnãoValor da parcela.
valor_emissaoDecimalnãoValor na emissão (relatórios ir_pcc_inss/terceiros_pj).
valor_pagamentoDecimalnãoValor efetivamente pago.
valor_brutoDecimalnãoValor do documento (só servicos_tomados preenche - não confundir com ipg_valor, que é a parcela).
ipg_irrfDecimalnãoIRRF retido. |valor| < 10.000.000.000.000.
ipg_inssDecimalnãoINSS retido. Mesmo limite de faixa.
ipg_issDecimalnãoISS retido. Mesmo limite de faixa.
ipg_imp_pisDecimalnãoPIS retido. Mesmo limite de faixa.
ipg_imp_cofinsDecimalnãoCOFINS retido. Mesmo limite de faixa.
ipg_imp_csslDecimalnãoCSLL retido. Mesmo limite de faixa.
indicstringnãoMáx. 20. Grupo/classificador do tributo. Parte da chave natural.
indic_1stringnãoMáx. 20. Classificador adicional de origem.
indic_2stringnãoMáx. 100. Tipo de compromisso, sem acento (ex.: Titulos).
fis_jurstringnãoMáx. 20. Natureza jurídica do credor (J/F).
cfostringnãoMáx. 300. Código fiscal de operação.
conta_contabilstringnãoMáx. 300. Conta contábil de destino.
bancostringnãoMáx. 100. Banco do pagamento.

SmartImpostosRetidosUpdate

Corpo do PUT /smart-impostos-retidos/{registro_id}. extra="forbid". Não aceita os 10 campos da chave natural: cnpj, tipo_relatorio, emp_cgc, cpg_serie, cpg_num, cpg_doc, cpg_dt_doc_emiss, ipg_parc, ipg_dt_pgto, indic.

Campo permitidoTipoCampo permitidoTipo
cfg_empstringipg_imp_pisDecimal
gcc_descrstringipg_imp_cofinsDecimal
cde_nomestringipg_imp_csslDecimal
cpg_credorstringindic_1string
total_parcintindic_2string
ipg_valorDecimalfis_jurstring
valor_emissaoDecimalcfostring
valor_pagamentoDecimalconta_contabilstring
valor_brutoDecimalbancostring
ipg_irrfDecimalipg_inssDecimal
ipg_issDecimal

SmartImpostosRetidosRead

Retorno de leitura. Estende SmartImpostosRetidosCreate com id e data_hora_criacao.

CampoTipoObservações
idintIdentificador do registro.
data_hora_criacaodatetimeData/hora de criação do registro.
(demais campos)-Todos os campos de SmartImpostosRetidosCreate, incluindo ipg_dt_pgto.

ImportacaoLoteRequest

Corpo do POST /smart-impostos-retidos/importar. extra="forbid". O envelope é a autoridade sobre tipo_relatorio/cnpj: o que vier no item é sobrescrito.

CampoTipoObrigatórioObservações
tipo_relatoriostringsimUm dos 4 valores do vocabulário acima.
cnpjstringsim1 a 30 caracteres. CNPJ do cliente da planilha.
itensList[ImportacaoItem]sim1 a 5000 itens.

ImportacaoItem aceita os mesmos campos de SmartImpostosRetidosCreate (exceto tipo_relatorio, que é opcional aqui pois vem do envelope), mais:

  • Aliases de nome por relatório: ir/inss/iss/pis/cofins/csll são aceitos como sinônimos de ipg_irrf/ipg_inss/ipg_iss/ipg_imp_pis/ipg_imp_cofins/ipg_imp_cssl; tipo_compromisso é sinônimo de indic_2; cpg_fis_jur/emp_fis_jur são sinônimos de fis_jur.
  • Os 7 campos mcc_irrf, mcc_inss, mcc_iss, mcc_imp_pis, mcc_imp_cofins, mcc_imp_cssl, mcc_valor_emissao (todos Decimal, opcionais) são aceitos e comparados com as colunas ipg_*/valor_emissao correspondentes, mas não são persistidos. Divergência entre um mcc_* e a coluna correspondente recusa o lote inteiro com 422.

ImportacaoResultado

Corpo de data na resposta de sucesso do POST /smart-impostos-retidos/importar.

CampoTipoObservações
totalintTotal de itens únicos processados (após dedup intra-lote).
criadosintQuantos viraram linha nova.
atualizadosintQuantos já existiam e tiveram colunas não-chave atualizadas.
duplicados_no_loteintItens com a mesma chave natural e payload idêntico, colapsados.
avisosList[string]Mensagens informativas (ex.: sobre itens colapsados).

Notas

  • Sucesso segue o envelope { status: "success", message, data }. Erros levantados como HTTPException (404, 409, 422) respondem { message } com o código HTTP correspondente.
  • A mesma retenção pode estar gravada até 4 vezes (uma por tipo_relatorio). Toda soma/agregação deve filtrar por tipo_relatorio em GET /smart-impostos-retidos/, sob risco de contar o mesmo valor múltiplas vezes.
  • Os 10 campos monetários (ipg_valor, valor_emissao, valor_pagamento, valor_bruto, ipg_irrf, ipg_inss, ipg_iss, ipg_imp_pis, ipg_imp_cofins, ipg_imp_cssl) são Decimal no schema e DECIMAL(15,2) no banco - divergindo de propósito do restante da família Smart, que usa float, porque este é o único domínio Smart cujo dado alimenta apuração de tributo.
  • valor_bruto (documento) e ipg_valor (parcela) não são a mesma coisa e não devem ser somados/fundidos - só coincidem quando o documento tem parcela única.
  • A chave natural (cnpj, tipo_relatorio, emp_cgc, cpg_serie, cpg_num, cpg_doc, cpg_dt_doc_emiss, ipg_parc, ipg_dt_pgto, indic) é a base da idempotência de POST /smart-impostos-retidos/importar e do conflito 409 do POST /smart-impostos-retidos/.
  • POST /smart-impostos-retidos/importar aceita no máximo 5000 itens por chamada; reimportar o mesmo lote não duplica linhas.