# API de envio e recuperação  de carga tributária ICMS + IBS/CBS

#### Visão geral

O ERP envia os produtos com a tributação atual em `POST /enviar-carga`, a CTS revisa de forma assíncrona e o ERP busca o resultado em `POST /recuperar-carga`. As duas chamadas usam o mesmo token e o mesmo CNPJ.

<table id="bkmrk-item-valor-url-base-" style="width: 79.881%; height: 195.578px;"><colgroup><col style="width: 21.4605%;"></col><col style="width: 78.3905%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><th colspan="1" rowspan="1" style="height: 29.7969px;">Item

</th><th colspan="1" rowspan="1" style="height: 29.7969px;">Valor

</th></tr><tr style="height: 29.7969px;"><td colspan="1" rowspan="1" style="height: 29.7969px;">URL base

</td><td colspan="1" rowspan="1" style="height: 29.7969px;">https://revisao-tributaria.cts.app.br/cts-revisao-tributaria</td></tr><tr style="height: 29.7969px;"><td colspan="1" rowspan="1" style="height: 29.7969px;">Formato

</td><td colspan="1" rowspan="1" style="height: 29.7969px;">JSON, UTF-8, header `Content-Type: application/json`

</td></tr><tr style="height: 29.7969px;"><td colspan="1" rowspan="1" style="height: 29.7969px;">Autenticação

</td><td colspan="1" rowspan="1" style="height: 29.7969px;">header `token` com o token do sistema cadastrado na CTS

</td></tr><tr style="height: 29.7969px;"><td colspan="1" rowspan="1" style="height: 29.7969px;">CNPJ

</td><td colspan="1" rowspan="1" style="height: 29.7969px;">raiz do CNPJ, 8 primeiros dígitos, só números (ex.: `92565464`)

</td></tr><tr style="height: 46.5938px;"><td colspan="1" rowspan="1" style="height: 46.5938px;">Limite por chamada

</td><td colspan="1" rowspan="1" style="height: 46.5938px;">5000 produtos, nas duas rotas

</td></tr></tbody></table>

Nos exemplos, troque `{URL_BASE}`, `SEU_TOKEN` e o CNPJ pelos valores do seu ambiente.

## 1. Enviar carga — `POST /enviar-carga`

Recebe até 5000 produtos por chamada e responde `202` assim que a carga é aceita. A revisão acontece depois; o resultado sai no recuperar-carga.

### Requisição

<table id="bkmrk-campo-onde-obrigat%C3%B3r"><colgroup><col></col><col></col><col></col><col></col></colgroup><tbody><tr><th colspan="1" rowspan="1">Campo

</th><th colspan="1" rowspan="1">Onde

</th><th colspan="1" rowspan="1">Obrigatório

</th><th colspan="1" rowspan="1">Regra

</th></tr><tr><td colspan="1" rowspan="1">`token`

</td><td colspan="1" rowspan="1">header

</td><td colspan="1" rowspan="1">sim

</td><td colspan="1" rowspan="1">token do sistema na CTS

</td></tr><tr><td colspan="1" rowspan="1">`operacao`

</td><td colspan="1" rowspan="1">body

</td><td colspan="1" rowspan="1">sim

</td><td colspan="1" rowspan="1">só `S` (saída)

</td></tr><tr><td colspan="1" rowspan="1">`uf`

</td><td colspan="1" rowspan="1">body

</td><td colspan="1" rowspan="1">sim

</td><td colspan="1" rowspan="1">sigla do estado, ex.: `RS`

</td></tr><tr><td colspan="1" rowspan="1">`cnpj`

</td><td colspan="1" rowspan="1">body

</td><td colspan="1" rowspan="1">sim

</td><td colspan="1" rowspan="1">raiz do CNPJ, 8 dígitos

</td></tr><tr><td colspan="1" rowspan="1">`produtos`

</td><td colspan="1" rowspan="1">body

</td><td colspan="1" rowspan="1">sim

</td><td colspan="1" rowspan="1">lista com 1 a 5000 produtos

</td></tr><tr><td colspan="1" rowspan="1">`Codigo`

</td><td colspan="1" rowspan="1">produto

</td><td colspan="1" rowspan="1">sim

</td><td colspan="1" rowspan="1">código do produto no ERP

</td></tr><tr><td colspan="1" rowspan="1">`EAN`

</td><td colspan="1" rowspan="1">produto

</td><td colspan="1" rowspan="1">sim

</td><td colspan="1" rowspan="1">código de barras

</td></tr><tr><td colspan="1" rowspan="1">`produtoDescricao`

</td><td colspan="1" rowspan="1">produto

</td><td colspan="1" rowspan="1">sim

</td><td colspan="1" rowspan="1">descrição do produto

</td></tr><tr><td colspan="1" rowspan="1">`ncm`

</td><td colspan="1" rowspan="1">produto

</td><td colspan="1" rowspan="1">sim

</td><td colspan="1" rowspan="1">NCM atual

</td></tr><tr><td colspan="1" rowspan="1">demais campos `trib*` e `cest`

</td><td colspan="1" rowspan="1">produto

</td><td colspan="1" rowspan="1">não

</td><td colspan="1" rowspan="1">tributação atual no ERP; envie vazio quando não houver

</td></tr></tbody></table>

Os nomes dos campos diferenciam maiúsculas de minúsculas: `Codigo` e `EAN` são escritos assim. O body inteiro pode ter até cerca de 12,8 MB (5000 × 2560 bytes); acima disso a carga é recusada sem ser lida.

### Exemplo

```bash
curl -i -X POST 'https://revisao-tributaria.cts.app.br/cts-revisao-tributaria/enviar-carga' \
  -H 'Content-Type: application/json' \
  -H 'token: SEU_TOKEN' \
  -d '{
    "operacao": "S",
    "uf": "RS",
    "cnpj": "92565464",
    "produtos": [
      {
        "Codigo": 96820,
        "EAN": "7898922378726",
        "produtoDescricao": "MAMAO LB 1 Un FORMOSA",
        "ncm": "08072000",
        "cest": "",
        "tribRegraCfop": "5102",
        "tribIcmsCst": "40",
        "tribIcmsReducao": "0.0",
        "tribIcmsAliq": "0.0",
        "tribIcmsStAliq": "0.0",
        "tribIcmsStPauta": "0",
        "tribIcmsStMva": "0.0",
        "tribFcpAliq": "0.0",
        "tribDifalAliq": "0",
        "tribPisCst": "06",
        "tribPisReducao": "",
        "tribPisAliq": "0.000",
        "tribIbsCbsCst": "200",
        "tribRedCbs": 100,
        "tribRedIbs": 100,
        "tribAliqCbs": 0.9,
        "tribAliqIbs": 0.1,
        "tribCclassTrib": "200014"
      }
    ]
  }'
```

### Retornos

**202 Accepted — carga recebida.** Guarde o `idRequisicao` para falar com o suporte da CTS.

```json
{
  "idRequisicao": 6052,
  "totalProdutos": 1,
  "mensagem": "Carga recebida com sucesso."
}
```

**400 — campos obrigatórios faltando.** A CTS confere todos os produtos e devolve todos os problemas de uma vez. Em `details`, `produto` é a posição na lista (começa em 1), seguido dos dados que identificam o produto como foram enviados (`null` quando faltam) e da lista `campos` com o que faltou. Nenhum produto da carga é gravado.

```json
{
  "code": 331,
  "message": "Campos obrigatórios não informados.",
  "details": [
    {
      "produto": 1,
      "Codigo": "96820",
      "EAN": "7898922378726",
      "produtoDescricao": "MAMAO LB 1 Un FORMOSA",
      "campos": ["ncm"]
    }
  ]
}
```

**400 — acima do limite.** Mais de 5000 produtos, ou body maior que o teto. Divida a carga em lotes menores e envie de novo.

```json
{
  "code": 327,
  "message": "050 - O máximo permitido 5000 produtos, por requisição."
}
```

Os outros erros (token, CNPJ, operação, UF, JSON inválido) estão na tabela de códigos de erro, mais abaixo. A ordem das validações é: limite, token, CNPJ e acesso, operação, UF, lista e campos dos produtos.

## 2. Recuperar carga — `POST /recuperar-carga`

Devolve até `limite` produtos já revisados pela CTS e os baixa na mesma chamada: um produto devolvido não volta em chamadas seguintes. Por isso grave a resposta no ERP antes de chamar de novo.

### Requisição

<table id="bkmrk-campo-onde-obrigat%C3%B3r-1"><colgroup><col></col><col></col><col></col><col></col></colgroup><tbody><tr><th colspan="1" rowspan="1">Campo

</th><th colspan="1" rowspan="1">Onde

</th><th colspan="1" rowspan="1">Obrigatório

</th><th colspan="1" rowspan="1">Regra

</th></tr><tr><td colspan="1" rowspan="1">`token`

</td><td colspan="1" rowspan="1">header

</td><td colspan="1" rowspan="1">sim

</td><td colspan="1" rowspan="1">o mesmo do enviar-carga

</td></tr><tr><td colspan="1" rowspan="1">`cnpj`

</td><td colspan="1" rowspan="1">body

</td><td colspan="1" rowspan="1">sim

</td><td colspan="1" rowspan="1">raiz do CNPJ, 8 dígitos

</td></tr><tr><td colspan="1" rowspan="1">`limite`

</td><td colspan="1" rowspan="1">body

</td><td colspan="1" rowspan="1">sim

</td><td colspan="1" rowspan="1">de 1 a 5000 produtos por chamada

</td></tr></tbody></table>

### Exemplo

```bash
curl -i -X POST 'https://revisao-tributaria.cts.app.br/cts-revisao-tributaria/recuperar-carga' \
  -H 'Content-Type: application/json' \
  -H 'token: SEU_TOKEN' \
  -d '{ "cnpj": "92565464", "limite": 200 }'
```

### Retornos

**200 OK — com produtos.** Os campos usam a mesma nomenclatura do enviar-carga, com os valores revisados pela CTS.

```json
{
  "produtos": [
    {
      "operacao": "S",
      "uf": "RS",
      "cnpj": "92565464",
      "Codigo": 96820,
      "EAN": "7898922378726",
      "produtoDescricao": "MAMAO LB 1 Un FORMOSA",
      "ncm": "08072000",
      "tribCfop": "5102",
      "tribIcmsCst": "40",
      "tribIcmsReducao": "0.0",
      "tribIcmsAliq": "0.0",
      "tribIcmsStAliq": "0.0",
      "tribIcmsStPauta": "0.0",
      "tribIcmsStMva": "0.0",
      "tribFcpAliq": "0.0",
      "tribDifalAliq": "0.0",
      "tribPisCst": "06",
      "tribPisReducao": "0.0",
      "tribPisAliq": "0.0",
      "tribIbsCbsCst": "200",
      "tribRedCbs": 100.0,
      "tribRedIbs": 100.0,
      "tribAliqCbs": 0.9,
      "tribAliqIbs": 0.1,
      "tribCclassTrib": "200014"
    }
  ],
  "TotalProdutoSolicitados": 200,
  "TotalProdutosRestante": 350
}
```

<table id="bkmrk-campo-significado-pr"><colgroup><col></col><col></col></colgroup><tbody><tr><th>Campo

</th><th>Significado

</th></tr><tr><td>`produtos`

</td><td>produtos revisados desta chamada; some da resposta quando não há nenhum

</td></tr><tr><td>`TotalProdutoSolicitados`

</td><td>o `limite` enviado na chamada (não é a quantidade devolvida; conte os itens de `produtos`)

</td></tr><tr><td>`TotalProdutosRestante`

</td><td>quantos produtos ainda esperam ser recuperados; chame de novo enquanto for maior que zero

</td></tr><tr><td>`Codigo`

</td><td>volta como número quando o código é só dígitos, senão como texto

</td></tr></tbody></table>

**200 OK — nada pendente.** A carga ainda está em processamento na CTS, ou tudo já foi recuperado.

```json
{
  "TotalProdutoSolicitados": 200,
  "TotalProdutosRestante": 0
}
```

**409 Conflict — chamada em andamento.** Já existe um recuperar-carga rodando com o mesmo CNPJ e token. Espere a primeira terminar e chame de novo; não faça chamadas em paralelo.

```json
{
  "code": 335,
  "message": "Já existe uma requisição em andamento para este CNPJ e token, aguarde a conclusão."
}
```

**400 — limite inválido.** `limite` ausente ou menor que 1 devolve o código 334; acima de 5000 devolve o 327, o mesmo do enviar-carga.

```json
{
  "code": 334,
  "message": "O limite deve ser informado e maior que zero."
}
```

## 3. Códigos de erro

Todo erro volta com o status HTTP e um JSON com `code` e `message`; alguns trazem também `details`. Trate pelo `code`, não pelo texto da mensagem.

```json
{ "code": 317, "message": "022 - Token nao Localizado no Ambiente Selecionado." }
```

<table id="bkmrk-http-code-mensagem-q" style="width: 100.833%;"><colgroup><col style="width: 8.22408%;"></col><col style="width: 12.3957%;"></col><col style="width: 24.6722%;"></col><col style="width: 30.2741%;"></col><col style="width: 11.5614%;"></col><col style="width: 12.9917%;"></col></colgroup><tbody><tr><th colspan="1" rowspan="1">HTTP

</th><th colspan="1" rowspan="1">code

</th><th colspan="1" rowspan="1">Mensagem

</th><th colspan="1" rowspan="1">Quando acontece

</th><th colspan="1" rowspan="1">Rotas

</th><th colspan="1" rowspan="1">O que fazer

</th></tr><tr><td colspan="1" rowspan="1">400

</td><td colspan="1" rowspan="1">101

</td><td colspan="1" rowspan="1">A lista de produtos não foi informado.

</td><td colspan="1" rowspan="1">body vazio, ou `produtos` ausente ou vazio

</td><td colspan="1" rowspan="1">enviar

</td><td colspan="1" rowspan="1">envie ao menos 1 produto

</td></tr><tr><td colspan="1" rowspan="1">400

</td><td colspan="1" rowspan="1">202

</td><td colspan="1" rowspan="1">O Cnpj não foi informado.

</td><td colspan="1" rowspan="1">`cnpj` ausente ou vazio

</td><td colspan="1" rowspan="1">as duas

</td><td colspan="1" rowspan="1">informe a raiz do CNPJ

</td></tr><tr><td colspan="1" rowspan="1">401

</td><td colspan="1" rowspan="1">317

</td><td colspan="1" rowspan="1">022 - Token nao Localizado no Ambiente Selecionado.

</td><td colspan="1" rowspan="1">header `token` ausente

</td><td colspan="1" rowspan="1">as duas

</td><td colspan="1" rowspan="1">envie o header `token`

</td></tr><tr><td colspan="1" rowspan="1">403

</td><td colspan="1" rowspan="1">324

</td><td colspan="1" rowspan="1">021 - Cliente não cadastrado no Sistema.

</td><td colspan="1" rowspan="1">CNPJ não está ligado a esse token

</td><td colspan="1" rowspan="1">as duas

</td><td colspan="1" rowspan="1">confira o CNPJ; peça o cadastro à CTS

</td></tr><tr><td colspan="1" rowspan="1">401

</td><td colspan="1" rowspan="1">325

</td><td colspan="1" rowspan="1">Sistema não Encontrado.

</td><td colspan="1" rowspan="1">token não existe na CTS

</td><td colspan="1" rowspan="1">as duas

</td><td colspan="1" rowspan="1">fale com a CTS

</td></tr><tr><td colspan="1" rowspan="1">403

</td><td colspan="1" rowspan="1">326

</td><td colspan="1" rowspan="1">024 - Token Desabilitado

</td><td colspan="1" rowspan="1">token inativo

</td><td colspan="1" rowspan="1">as duas

</td><td colspan="1" rowspan="1">fale com a CTS

</td></tr><tr><td colspan="1" rowspan="1">400

</td><td colspan="1" rowspan="1">327

</td><td colspan="1" rowspan="1">050 - O máximo permitido 5000 produtos, por requisição.

</td><td colspan="1" rowspan="1">mais de 5000 produtos, body acima do teto, ou `limite` acima de 5000

</td><td colspan="1" rowspan="1">as duas

</td><td colspan="1" rowspan="1">divida em lotes ou reduza o `limite`

</td></tr><tr><td colspan="1" rowspan="1">400

</td><td colspan="1" rowspan="1">330

</td><td colspan="1" rowspan="1">Operação inválida, informe S.

</td><td colspan="1" rowspan="1">`operacao` diferente de `S`

</td><td colspan="1" rowspan="1">enviar

</td><td colspan="1" rowspan="1">envie `"operacao": "S"`

</td></tr><tr><td colspan="1" rowspan="1">400

</td><td colspan="1" rowspan="1">331

</td><td colspan="1" rowspan="1">Campos obrigatórios não informados.

</td><td colspan="1" rowspan="1">produto sem `Codigo`, `EAN`, `produtoDescricao` ou `ncm`

</td><td colspan="1" rowspan="1">enviar

</td><td colspan="1" rowspan="1">corrija os produtos listados em `details`

</td></tr><tr><td colspan="1" rowspan="1">400

</td><td colspan="1" rowspan="1">332

</td><td colspan="1" rowspan="1">A UF deve ser informada.

</td><td colspan="1" rowspan="1">`uf` ausente

</td><td colspan="1" rowspan="1">enviar

</td><td colspan="1" rowspan="1">informe a sigla do estado

</td></tr><tr><td colspan="1" rowspan="1">400

</td><td colspan="1" rowspan="1">333

</td><td colspan="1" rowspan="1">UF inválida, informe a sigla do estado (ex.: RS).

</td><td colspan="1" rowspan="1">`uf` não é uma das 27 siglas

</td><td colspan="1" rowspan="1">enviar

</td><td colspan="1" rowspan="1">corrija a sigla

</td></tr><tr><td colspan="1" rowspan="1">400

</td><td colspan="1" rowspan="1">334

</td><td colspan="1" rowspan="1">O limite deve ser informado e maior que zero.

</td><td colspan="1" rowspan="1">`limite` ausente ou menor que 1

</td><td colspan="1" rowspan="1">recuperar

</td><td colspan="1" rowspan="1">envie `limite` de 1 a 5000

</td></tr><tr><td colspan="1" rowspan="1">409

</td><td colspan="1" rowspan="1">335

</td><td colspan="1" rowspan="1">Já existe uma requisição em andamento para este CNPJ e token, aguarde a conclusão.

</td><td colspan="1" rowspan="1">outra chamada igual ainda está rodando

</td><td colspan="1" rowspan="1">recuperar

</td><td colspan="1" rowspan="1">espere e chame de novo

</td></tr><tr><td colspan="1" rowspan="1">400

</td><td colspan="1" rowspan="1">400

</td><td colspan="1" rowspan="1">Parâmetros de requisição inválidos.

</td><td colspan="1" rowspan="1">JSON mal formado ou que não é um objeto; `details` traz o motivo

</td><td colspan="1" rowspan="1">as duas

</td><td colspan="1" rowspan="1">corrija o JSON

</td></tr><tr><td colspan="1" rowspan="1">500

</td><td colspan="1" rowspan="1">401

</td><td colspan="1" rowspan="1">Erro interno, favor contactar o administrador.

</td><td colspan="1" rowspan="1">falha inesperada na CTS

</td><td colspan="1" rowspan="1">as duas

</td><td colspan="1" rowspan="1">tente de novo; se repetir, fale com a CTS

</td></tr></tbody></table>

## 4. Como o ERP deve consumir

1. Envie a carga em lotes de até 5000 produtos pelo enviar-carga e guarde o `idRequisicao` de cada lote.
2. Aguarde o processamento da CTS; ele é assíncrono e pode levar alguns minutos.
3. Chame o recuperar-carga com um `limite` fixo, por exemplo 200.
4. Grave os produtos recebidos no ERP antes da próxima chamada: eles não serão devolvidos de novo.
5. Repita o passo 3 enquanto `TotalProdutosRestante` for maior que zero.
6. Com `TotalProdutosRestante` igual a zero e nenhum produto na resposta, pare e tente de novo mais tarde.

- Faça uma chamada de recuperar-carga por vez para cada CNPJ e token; chamadas em paralelo recebem `409`.
- Em `409` ou `500`, espere alguns segundos antes de repetir. Erros `400`, `401` e `403` não se resolvem repetindo: corrija a chamada.
- Use sempre o mesmo token e a mesma raiz de CNPJ no envio e na recuperação.