{
  "openapi": "3.0.3",
  "info": {
    "title": "API Pública Sudrel: NFS-e, NF-e e CT-e",
    "version": "1.0",
    "description": "API da Sudrel para **emitir NFS-e** e para **consultar NFS-e, NF-e e CT-e**\ndas suas empresas, com webhooks assinados e log de eventos. Os mesmos dados\ndo [painel](https://sudrel.com.br/painel), para o seu ERP, sistema contábil\nou automação interna.\n\n## O que você quer fazer?\n\n| Quero... | Comece por |\n|---|---|\n| **Emitir uma NFS-e** e saber o resultado | [Sua primeira nota](#tag/comece-aqui), depois `POST /v1/nfse` |\n| **Emitir muitas notas** de uma vez (até 5.000) | [Emissão em lote](#tag/emissão-em-lote) |\n| **Consultar documentos** recebidos ou emitidos (NFS-e, NF-e, CT-e) | [Documentos](#tag/documentos), `GET /v1/documents` |\n| **Ser avisado** quando algo muda, sem ficar consultando | [Webhooks](#tag/webhooks) e [Eventos](#tag/eventos) |\n| **Testar falhas** antes de ir para produção | [Simulador de falhas](#tag/simulador-de-falhas) |\n| **Usar a Sudrel num assistente de IA** | [IA e MCP](#tag/ia-e-mcp) |\n| **Usar SDK, OpenAPI ou Postman** | [SDKs](#tag/sdks) e [OpenAPI e Postman](#tag/openapi-e-postman) |\n| **Entender um erro** | [Erros e status HTTP](#tag/erros-e-status-http) e [Problemas comuns](#tag/problemas-comuns) |\n\nAntes de ir para produção, leia as [Regras de integração](#tag/regras-de-integração):\nsão doze, curtas, e evitam nota duplicada e retentativa errada.\n\n## O que a API faz\n\n| Documento | Emitir | Consultar |\n|---|---|---|\n| NFS-e | Sim: `POST /v1/nfse` e `POST /v1/lotes`, pelo Sistema Nacional NFS-e (e pelo sistema da prefeitura nos municípios que ainda não usam o nacional) | Sim: as emitidas pela Sudrel em `GET /v1/nfse`; as recebidas e as emitidas por qualquer sistema em `GET /v1/documents` |\n| NF-e | Não | Sim, em `GET /v1/documents` |\n| CT-e | Não | Sim, em `GET /v1/documents` |\n\nAlém disso: cadastro de empresas e certificado A1 (`/v1/companies`), prontidão\npara emitir, webhooks (`/v1/webhooks`), log de eventos (`/v1/eventos`), conta\ne consumo (`/v1/account`, `/v1/usage`).\n\n## Como a API funciona\n\n```text\nSeu sistema\n    |\n    |  HTTPS + chave de API (Authorization: Bearer sdr_...)\n    v\nSudrel API  https://api.sudrel.com.br/api\n    |\n    +-- Empresas e prontidão ........ /v1/companies\n    +-- NFS-e e lotes ............... /v1/nfse, /v1/lotes  ---> Sistema Nacional NFS-e\n    +-- Documentos .................. /v1/documents        <--- Ambiente de Dados Nacional e SEFAZ\n    +-- Webhooks e eventos .......... /v1/webhooks, /v1/eventos  ---> seu sistema\n```\n\nUma emissão:\n\n```text\nPOST /v1/nfse\n   |\n   +-- 412 empresa_nao_pronta ou 422 validacao --> nada foi criado: corrija e envie de novo\n   |\n   +-- nota criada e transmitida (a chamada espera até 10 s; Prefer: wait=N muda isso)\n          |\n          +-- 201 autorizada --------------------> pronto: numero e chave_acesso\n          +-- 422 nfse_rejeitada ----------------> a nota existe, rejeitada: corrija e emita outra\n          +-- 202 transmitindo ------------------> a Sudrel continua cuidando:\n                                                   webhook NFSE_AUTORIZADA / NFSE_REJEITADA\n                                                   ou GET /v1/nfse/{id}\n```\n\n**202 não é erro.** Quer dizer \"recebido, ainda em andamento\". Veja\n[Estados da NFS-e](#tag/estados-da-nfs-e).\n\n## Endereço base\n\n```text\nhttps://api.sudrel.com.br/api\n```\n\nToda rota começa por `/v1`. Nesta documentação os caminhos aparecem sem o\nendereço base: `POST /v1/nfse` é\n`POST https://api.sudrel.com.br/api/v1/nfse`.\n\nTeste e produção usam o **mesmo endereço**. Quem decide o ambiente é a chave.\n\n## Autenticação\n\nToda chamada exige uma chave de API no cabeçalho `Authorization`:\n\n```\nAuthorization: Bearer sdr_live_xxxxxxxxxxxxxxxxxxxxxxxx\n```\n\nGere uma chave em **Painel → Chaves de API**\n(`/painel/chaves-api`). Ela é exibida **uma única vez** no momento da\ncriação — se perder, revogue e crie outra.\n\nExistem dois tipos de chave:\n\n| Prefixo | Ambiente | O que faz |\n|---|---|---|\n| `sdr_live_...` | Produção | Tudo: empresas, documentos recebidos e emissão de NFS-e com valor fiscal. |\n| `sdr_test_...` | Teste de emissão | Só emissão de NFS-e, no ambiente de testes do Sistema Nacional (produção restrita), com as suas empresas e o certificado real. Lê a lista de empresas, mas não altera empresa nem lê documento recebido. |\n\nUma chave pode ser restrita a uma única empresa, e aí só enxerga essa\nempresa.\n\nToda resposta traz o cabeçalho `X-Request-Id`. Nas rotas de emissão, lote,\nwebhooks e eventos, o corpo de erro repete o mesmo valor em `requisicao_id`.\nGuarde esse id: com ele você acha a chamada em **Integrações › Log da API**,\npor 30 dias.\n\n## Teste e produção\n\n| | Teste (`sdr_test_`) | Produção (`sdr_live_`) |\n|---|---|---|\n| Endereço | `https://api.sudrel.com.br/api` | O mesmo |\n| Para onde vai a nota | Produção restrita do Sistema Nacional (o ambiente de testes oficial), de verdade | Produção do Sistema Nacional |\n| Valor fiscal | Não | Sim |\n| Conta na franquia, exige plano | Não | Sim |\n| Certificado | O certificado real da empresa | O mesmo |\n| Aparece no painel | Não | Sim |\n| Empresas | Lê. Não cria nem altera (403) | Lê, cria e altera |\n| Documentos recebidos | Não (403) | Sim |\n| Webhooks e eventos | Só os de teste | Só os de produção |\n| Itens por lote | Até 100 | Até 5.000 |\n| [Simulador de falhas](#tag/simulador-de-falhas) | Sim | Não (422 `simulacao_so_no_sandbox`) |\n| Série da DPS | `49999` | A da empresa |\n\nOs dois ambientes nunca se cruzam: a chave de teste só enxerga notas, lotes,\nwebhooks e eventos de teste, e a de produção só os de produção. A mesma\n`referencia` e a mesma `Idempotency-Key` podem ser usadas nos dois.\n\nEmpresa que emite pelo sistema da prefeitura não tem ambiente de teste: com a\nchave de teste, a prontidão vem com o item `sandbox_municipio_proprio` em\n`bloqueio`, e a emissão é recusada com 412 `empresa_nao_pronta`.\n\n## Passar para produção\n\n1. Crie uma chave `sdr_live_` no painel. As rotas e o JSON são os mesmos: só\n   a chave muda.\n2. Consulte a prontidão com a chave nova (`GET /v1/companies/{id}/prontidao`).\n   Em produção ela também confere o plano de Emissão (`plano_emissao`).\n3. Cadastre o webhook de produção. O webhook criado com a chave de teste só\n   recebe eventos de teste.\n4. Guarde `X-Request-Id` (ou `requisicao_id`) nos seus logs desde o primeiro dia.\n"
  },
  "servers": [
    {
      "url": "https://api.sudrel.com.br/api",
      "description": "Produção"
    }
  ],
  "security": [
    {
      "chaveApi": []
    }
  ],
  "tags": [
    {
      "name": "Comece aqui",
      "x-resumo": "Da chave de teste à primeira NFS-e autorizada, passo a passo, com curl, C# e Delphi.",
      "description": "### Sua primeira nota\n\nTudo começa no ambiente de teste: a nota vai de verdade ao ambiente de testes\ndo Sistema Nacional, sem valor fiscal, sem cobrar e sem aparecer no painel.\nPara produção, depois, só a chave muda.\n\n**Qual caminho é o seu?**\n\n- **A. A empresa já está configurada no painel** (certificado A1 e dados\n  fiscais): faça os passos 1, 3, 5, 6 e 7 (o 4 é opcional). Leva minutos.\n- **B. Primeira configuração:** comece pelo passo 2. O tempo depende de ter o\n  certificado A1 em mãos e de conhecer o regime tributário e o código de\n  serviço da empresa.\n\n**1. Chave de teste.** No painel, em **Integrações › Chaves de API**, crie\numa chave com ambiente **Teste**. Ela começa com `sdr_test_`. Nos exemplos\nabaixo ela está na variável `SUDREL_API_KEY`.\n\n**2. Empresa (só no caminho B).** Cadastre a empresa e envie o certificado A1\npelo painel, ou pela API com uma chave `sdr_live_` (`POST /v1/companies` e\n`POST /v1/companies/{id}/certificate`). A chave de teste lê as empresas e\nemite em nome delas, mas não cria nem altera empresa. Os dados fiscais\n(regime tributário, código de serviço padrão) ficam no painel, em\n**Emissão › Empresa**. O `empresa_id` de cada empresa sai de\n`GET /v1/companies`.\n\n**3. Prontidão.** Objetivo: saber se a empresa pode emitir agora, antes de\ntentar.\n\n```bash\ncurl https://api.sudrel.com.br/api/v1/companies/$EMPRESA/prontidao \\\n  -H \"Authorization: Bearer $SUDREL_API_KEY\"\n```\n\nA resposta tem `situacao` (`ok`, `aviso` ou `bloqueio`) e um item por\nrequisito, cada um com `mensagem` e `correcao`. Próximo passo: com `ok` ou\n`aviso`, siga. Com `bloqueio`, resolva o item indicado: a emissão seria\nrecusada com 412. Detalhes em [Prontidão](#tag/prontidão).\n\n**4. Valide antes de emitir (opcional).** `POST /v1/nfse/validacoes` recebe\no mesmo JSON da emissão e devolve os erros e os `ajustes`, sem criar nada. A\nemissão faz as mesmas conferências antes de criar a nota, então este passo\nserve para conferir no seu sistema antes, não é obrigatório.\n\n```bash\ncurl https://api.sudrel.com.br/api/v1/nfse/validacoes \\\n  -H \"Authorization: Bearer $SUDREL_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"empresa_id\":\"'$EMPRESA'\",\"referencia\":\"PED-1001\",\"tomador\":{\"documento\":\"11222333000181\"},\"valor\":\"1500.00\",\"servico\":{\"descricao\":\"Consultoria em sistemas\"}}'\n```\n\nA resposta é sempre 200, com `valida` (`true` ou `false`), `erros` (cada um\ncom `campo`, `mensagem` e `correcao`) e `ajustes` (o que a Sudrel preencheu ou\nomitiu pelo município). Próximo passo: com `valida: true`, emita.\n\nVai emitir NF-e (mercadoria)? O caminho é parecido e está em\n[Início rápido de NF-e](#tag/início-rápido-de-nf-e).\n\n**5. Emita.** Mande sempre `referencia` e `Idempotency-Key`: é o que torna\nseguro repetir a chamada. Veja [Idempotência](#tag/idempotência).\n\n```bash\ncurl https://api.sudrel.com.br/api/v1/nfse \\\n  -H \"Authorization: Bearer $SUDREL_API_KEY\" \\\n  -H \"Idempotency-Key: 7f1c0d9a-4a51-4e0e-9b1f-2b6f0d3c5a10\" \\\n  -H \"Prefer: wait=10\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"empresa_id\":\"'$EMPRESA'\",\"referencia\":\"PED-1001\",\"tomador\":{\"documento\":\"11222333000181\"},\"valor\":\"1500.00\",\"servico\":{\"descricao\":\"Consultoria em sistemas\"}}'\n```\n\nO que pode voltar:\n\n| Status | O que aconteceu | Próximo passo |\n|---|---|---|\n| 201 | Autorizada. `numero` e `chave_acesso` preenchidos. | Pronto. Baixe o PDF em `GET /v1/nfse/{id}/pdf`. |\n| 202 | Ainda `transmitindo`. A Sudrel continua cuidando. | Espere o webhook ou consulte (passo 6). **Não emita de novo.** |\n| 422 `validacao` | O JSON tem erro. Nada foi criado. | Corrija os itens de `erros` e envie de novo. |\n| 422 `nfse_rejeitada` | O Sistema Nacional recusou. A nota existe como `rejeitada`. | Leia `rejeicao`, corrija e emita uma nota nova, com outra `referencia`. |\n| 412 `empresa_nao_pronta` | A empresa não pode emitir. Nada foi criado. | Resolva os itens em `bloqueio` (passo 3). |\n\nSem SDK, a mesma chamada em HTTP puro:\n\nC# (.NET 6 ou mais novo):\n\n```csharp\nusing System;\nusing System.Net.Http;\nusing System.Net.Http.Headers;\nusing System.Net.Http.Json;\nusing System.Threading.Tasks;\n\npublic static class PrimeiraNota\n{\n    // A Idempotency-Key é sua: gere uma por nota, guarde junto do pedido e\n    // reaproveite a MESMA se precisar repetir a chamada. Assim nunca sai nota dobrada.\n    public static async Task<string> EmitirAsync(string empresaId, string idempotencyKey)\n    {\n        using var http = new HttpClient { BaseAddress = new Uri(\"https://api.sudrel.com.br/api/\") };\n        http.DefaultRequestHeaders.Authorization =\n            new AuthenticationHeaderValue(\"Bearer\", Environment.GetEnvironmentVariable(\"SUDREL_API_KEY\"));\n\n        var pedido = new HttpRequestMessage(HttpMethod.Post, \"v1/nfse\")\n        {\n            Content = JsonContent.Create(new\n            {\n                empresa_id = empresaId,\n                referencia = \"PED-1001\",\n                tomador = new { documento = \"11222333000181\" },\n                valor = \"1500.00\",\n                servico = new { descricao = \"Consultoria em sistemas\" },\n            }),\n        };\n        pedido.Headers.Add(\"Idempotency-Key\", idempotencyKey);\n        pedido.Headers.Add(\"Prefer\", \"wait=10\");\n\n        var resposta = await http.SendAsync(pedido);\n        var corpo = await resposta.Content.ReadAsStringAsync();\n        // 201: autorizada. 202: ainda transmitindo (acompanhe por webhook ou GET /v1/nfse/PED-1001).\n        // 422: veja \"codigo\" e \"erros\" (ou a nota rejeitada em \"nfse\"). Todo erro traz \"requisicao_id\".\n        return $\"{(int)resposta.StatusCode} {corpo}\";\n    }\n}\n```\n\nDelphi (10.3 ou mais novo, `System.Net.HttpClient`):\n\n```pascal\nuses\n  System.SysUtils, System.Classes, System.Net.HttpClient, System.Net.URLClient;\n\n// A Idempotency-Key é sua: gere uma por nota, guarde junto do pedido e\n// reaproveite a MESMA se precisar repetir a chamada. Assim nunca sai nota dobrada.\nfunction EmitirNota(const EmpresaId, IdempotencyKey: string): string;\nvar\n  Cliente: THTTPClient;\n  Corpo: TStringStream;\n  Resposta: IHTTPResponse;\nbegin\n  Cliente := THTTPClient.Create;\n  Corpo := TStringStream.Create(\n    '{\"empresa_id\":\"' + EmpresaId + '\",\"referencia\":\"PED-1001\",' +\n    '\"tomador\":{\"documento\":\"11222333000181\"},\"valor\":\"1500.00\",' +\n    '\"servico\":{\"descricao\":\"Consultoria em sistemas\"}}', TEncoding.UTF8);\n  try\n    Cliente.ContentType := 'application/json';\n    Cliente.CustomHeaders['Authorization'] := 'Bearer ' + GetEnvironmentVariable('SUDREL_API_KEY');\n    Cliente.CustomHeaders['Idempotency-Key'] := IdempotencyKey;\n    Cliente.CustomHeaders['Prefer'] := 'wait=10';\n    Resposta := Cliente.Post('https://api.sudrel.com.br/api/v1/nfse', Corpo);\n    // 201: autorizada. 202: ainda transmitindo (acompanhe por webhook ou GET /v1/nfse/PED-1001).\n    // 422: veja \"codigo\" e \"erros\" (ou a nota rejeitada em \"nfse\"). Todo erro traz \"requisicao_id\".\n    Result := IntToStr(Resposta.StatusCode) + ' ' + Resposta.ContentAsString(TEncoding.UTF8);\n  finally\n    Corpo.Free;\n    Cliente.Free;\n  end;\nend;\n```\n\nHá também SDKs de TypeScript e PHP: veja [SDKs](#tag/sdks).\n\n**6. Acompanhe.** Objetivo: saber o resultado de uma nota que voltou 202.\nConsulte pela sua referência:\n\n```bash\ncurl https://api.sudrel.com.br/api/v1/nfse/PED-1001 \\\n  -H \"Authorization: Bearer $SUDREL_API_KEY\"\n```\n\nPróximo passo: `status` diz onde a nota está (veja\n[Estados da NFS-e](#tag/estados-da-nfs-e)). Consulte com calma (a cada 30\nsegundos, por exemplo); em produção, prefira o webhook.\n\n**7. Webhook.** Objetivo: ser avisado sem consultar. Cadastre um endereço\nseu, com a chave de teste (ele recebe só eventos de teste):\n\n```bash\ncurl https://api.sudrel.com.br/api/v1/webhooks \\\n  -H \"Authorization: Bearer $SUDREL_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\":\"https://erp.exemplo.com.br/webhooks/sudrel\",\"eventos\":[\"NFSE_AUTORIZADA\",\"NFSE_REJEITADA\",\"NFSE_FALHA_TRANSMISSAO\"]}'\n```\n\nGuarde o `segredo` da resposta: ele só aparece aqui. Teste com\n`POST /v1/webhooks/{id}/teste`. Como conferir a assinatura de cada entrega\nestá em [Webhooks](#tag/webhooks).\n\n**8. Provoque as falhas.** Com o cabeçalho `X-Sudrel-Simular` (seção\n[Simulador de falhas](#tag/simulador-de-falhas)) você vê timeout, Sefin fora,\ntrava de competência e `falha_transmissao` sem tocar na Sefin.\n\n**Deu erro?** Toda resposta traz o cabeçalho `X-Request-Id`, e os erros de\nemissão, lote, webhooks e eventos repetem o valor em `requisicao_id`. Procure\npor ele no painel, em **Integrações › Log da API**: está lá o que o seu\nsistema mandou e o que a Sudrel respondeu, por 30 dias. Veja também\n[Problemas comuns](#tag/problemas-comuns).\n"
    },
    {
      "name": "Regras de integração",
      "x-resumo": "As doze regras que evitam nota duplicada, retentativa errada e limite estourado.",
      "description": "Doze regras. Cada uma evita um problema real de integração.\n\n1. **Mande `Idempotency-Key` em `POST /v1/nfse` e `POST /v1/lotes`.** Não é\n   obrigatório, mas sem ele um timeout seguido de retentativa pode criar uma\n   segunda nota. Veja [Idempotência](#tag/idempotência).\n2. **Ao repetir a mesma tentativa, use a MESMA `Idempotency-Key`.** Gere uma\n   por nota, guarde junto do pedido e reaproveite. Chave nova é nota nova.\n3. **Mande `referencia` em toda nota** (o número do seu pedido, por\n   exemplo). Ela é única por empresa e ambiente: uma segunda nota com a mesma\n   `referencia` é recusada (409 `referencia_duplicada`). É a proteção que\n   continua valendo depois dos 30 dias em que a `Idempotency-Key` fica guardada.\n4. **202 não é erro.** A nota existe e está `transmitindo`. Acompanhe; não\n   emita de novo.\n5. **Em produção, prefira webhook a consulta repetida.** Assine\n   `NFSE_AUTORIZADA`, `NFSE_REJEITADA` e `NFSE_FALHA_TRANSMISSAO`.\n6. **Se consultar, consulte com calma.** O limite é de 120 requisições por\n   minuto por chave, e a nota em `transmitindo` não muda a cada segundo. Uma\n   consulta a cada 30 segundos por nota basta.\n7. **Dinheiro e alíquota vão como texto com ponto decimal**: `\"1500.00\"`,\n   `\"2\"`. Número JSON é recusado (`tipo_invalido`).\n8. **Programe em cima de `codigo`, nunca de `mensagem`.** A mensagem é para\n   gente e pode mudar de texto; o `codigo` é estável.\n9. **Guarde `X-Request-Id` (ou `requisicao_id`)** de toda chamada que deu\n   errado. Com ele você acha a chamada em **Integrações › Log da API**.\n10. **Trate cursor como valor opaco.** Guarde e devolva exatamente como veio,\n    sem interpretar nem montar. Veja [Paginação e limites](#tag/paginação-e-limites).\n11. **Só repita o que pode dar certo repetido.** Repita quando o erro traz\n    `retentavel: true`, em 429, 5xx e timeout, sempre com a mesma\n    `Idempotency-Key`. Não repita 400, 401, 403, 404, 409, 412 nem 422 sem\n    corrigir antes. Veja a [receita de retentativa](#tag/receitas).\n12. **Diante de `falha_transmissao`, leia `falha.dps_enviada` antes de emitir\n    de novo.** Com `\"desconhecido\"`, a nota pode ter sido emitida: confira no\n    Emissor Nacional primeiro.\n"
    },
    {
      "name": "Idempotência",
      "x-resumo": "Como Idempotency-Key e referencia impedem nota duplicada, e como repetir uma chamada com segurança.",
      "description": "### Como evitar nota duplicada\n\nDuas proteções, que se completam:\n\n| | `Idempotency-Key` (cabeçalho) | `referencia` (campo do corpo) |\n|---|---|---|\n| O que é | Identificador da SUA tentativa de chamada | Identificador da nota no SEU sistema (ex.: número do pedido) |\n| Onde vale | `POST /v1/nfse`, `POST /v1/lotes`, `POST /v1/webhooks` e `POST /v1/companies` | `POST /v1/nfse` e cada item de `POST /v1/lotes` |\n| Obrigatório | Não, mas recomendado | Não, mas recomendado |\n| Escopo | Conta e ambiente (vale para todas as chaves de API da conta naquele ambiente) | Empresa e ambiente |\n| Validade | 24 horas de uso exclusivo; a resposta fica guardada por 30 dias | Para sempre |\n| Repetida | Devolve a resposta gravada da primeira vez | 409 `referencia_duplicada`, com o `nfse_id` da nota que já existe |\n| Tamanho | Texto livre (um UUID serve) | Até 60 caracteres |\n\nUse as duas. A `Idempotency-Key` resolve a retentativa imediata (timeout,\nqueda de rede). A `referencia` impede a nota dobrada sempre, mesmo que o seu\nsistema perca a chave.\n\n### O que acontece em cada caso\n\n| Situação | Resultado |\n|---|---|\n| Mesma `Idempotency-Key`, mesmo corpo | A MESMA resposta da primeira vez (status e corpo), sem criar nada. Vale para 201, 202 e para os 422 `nfse_rejeitada` e `falha_transmissao`. |\n| Mesma `Idempotency-Key`, corpo diferente | 409 `idempotencia_conflito`. Nada é criado. |\n| A primeira chamada com a chave ainda está em andamento | A segunda espera cerca de 3 segundos. Se a primeira não terminou, 409 `conflito`: espere e repita. |\n| A primeira chamada terminou em erro sem criar nada (412, 422 `validacao`, 409 `referencia_duplicada`, 403, 404, 500) | Nada fica gravado: repetir com a mesma chave executa de novo. |\n| Passaram 24 horas, mesmo corpo | A MESMA resposta da primeira vez, como antes. A mesma requisição nunca vira duas notas, enquanto o registro existir (30 dias). |\n| Passaram 24 horas, corpo diferente | A chave está livre: é um pedido novo e é executado. |\n| Passaram 30 dias | O registro da chave foi apagado: a chave vale como nova. A `referencia` continua protegendo. |\n\nO corpo é comparado como JSON, com as chaves em ordem: espaço e ordem dos\ncampos não contam. Em `POST /v1/lotes` com planilha, o \"corpo\" é o arquivo\n(hash) mais os campos do formulário.\n\n**A resposta repetida é a foto da primeira.** Se a primeira chamada voltou\n202 `transmitindo` e a nota autorizou depois, repetir a chamada devolve o\nmesmo 202. Para o status de agora, use `GET /v1/nfse/{id}`.\n\n### Retentativa certa\n\n```text\nseu sistema                                   Sudrel\n    |  POST /v1/nfse                              |\n    |  Idempotency-Key: 7f1c...  referencia: PED-1001\n    |-------------------------------------------->|\n    |            (timeout: a resposta se perdeu)  |  a nota foi criada\n    |                                             |\n    |  POST /v1/nfse  (MESMA chave, MESMO corpo)  |\n    |-------------------------------------------->|\n    |<--------------------------------------------|  mesma resposta, mesma nota\n```\n\n> **Nunca gere uma `Idempotency-Key` nova para repetir a mesma nota.**\n> Chave nova é pedido novo. Se a `referencia` também for nova, sai outra nota.\n\nEm lote, mande `referencia` em cada item: a linha cuja referência já virou nota\naparece como `ja_existente` e não vira outra nota. Veja\n[Emissão em lote](#tag/emissão-em-lote).\n"
    },
    {
      "name": "Erros e status HTTP",
      "x-resumo": "Os dois formatos de erro, o que cada status HTTP significa e o catálogo de códigos.",
      "description": "### Dois formatos de erro\n\nA API tem dois formatos de erro. É herança das duas partes do produto, e o\ncontrato está congelado: os dois continuam como estão.\n\n| Rotas | Formato | `Content-Type` |\n|---|---|---|\n| `/v1/nfse`, `/v1/lotes`, `/v1/webhooks`, `/v1/eventos` | problem+json, com `codigo` estável | `application/problem+json` |\n| `/v1/account`, `/v1/usage`, `/v1/companies`, `/v1/documents`, `/v1/servicos`, `/v1/municipios` | Formato do NestJS | `application/json` |\n\n**problem+json** (emissão, lote, webhooks e eventos):\n\n```json\n{\n  \"type\": \"https://sudrel.com.br/docs/erros/referencia_duplicada\",\n  \"codigo\": \"referencia_duplicada\",\n  \"codigo_oficial\": null,\n  \"campo\": \"/referencia\",\n  \"mensagem\": \"Já existe uma nota com esta referência nesta empresa.\",\n  \"correcao\": \"Consulte a nota existente em GET /v1/nfse/9d2f0c1e-3a4b-4c5d-8e9f-0a1b2c3d4e5f. Se quiser emitir outra nota, use outra referência.\",\n  \"retentavel\": false,\n  \"nfse_id\": \"9d2f0c1e-3a4b-4c5d-8e9f-0a1b2c3d4e5f\",\n  \"requisicao_id\": \"b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e\"\n}\n```\n\n| Campo | Para que serve |\n|---|---|\n| `codigo` | Estável. **É nele que o seu código decide.** |\n| `codigo_oficial` | Código do Sistema Nacional (ex.: `E0240`), quando o erro vem de uma regra dele. |\n| `campo` | JSON Pointer do campo com problema no seu corpo (ex.: `/tomador/documento`). |\n| `mensagem` | Texto para gente. Pode mudar de redação; não compare. |\n| `correcao` | O que fazer. |\n| `retentavel` | `true`: repetir a MESMA requisição pode dar certo. `false`: corrija antes. |\n| `requisicao_id` | O mesmo valor do cabeçalho `X-Request-Id`. Procure por ele em **Integrações › Log da API**. |\n| `erros` | Em 422 `validacao`: todos os erros de uma vez, cada um com os campos acima. |\n| `itens` | Em 412 `empresa_nao_pronta`: a prontidão inteira. |\n| `nfse_id`, `nfse` | Em 409 `referencia_duplicada` (só `nfse_id`) e nos 422 `nfse_rejeitada` e `falha_transmissao` (a nota inteira em `nfse`). |\n\nNão há `title`, `status`, `detail` nem `instance`: o status está na resposta\nHTTP, e o `codigo` diz o resto.\n\n**Formato do NestJS** (conta, consumo, empresas, documentos, NBS, município):\n\n```json\n{ \"statusCode\": 404, \"message\": \"Empresa não encontrada nesta conta.\", \"error\": \"Not Found\" }\n```\n\n`message` pode ser uma string ou uma lista de strings (erro de validação de\nparâmetros, um item por campo). Aqui não há `requisicao_id` no corpo: use o\ncabeçalho `X-Request-Id`.\n\n### Status HTTP\n\n| Status | Significa | O que fazer |\n|---|---|---|\n| 200 | OK | Ler o corpo. |\n| 201 | Criado. Em `POST /v1/nfse`: nota autorizada. | Seguir. |\n| 202 | Aceito, ainda em andamento (nota `transmitindo`, lote em validação). **Não é erro.** | Acompanhar por webhook ou `GET`. Não repetir a criação. |\n| 204 | Removido. | Nada. |\n| 400 | Parâmetro de consulta inválido (`parametro_invalido`), ou parâmetro desconhecido nas rotas de documentos. | Corrigir a chamada. |\n| 401 | Chave ausente, inválida ou revogada (`nao_autenticado`). | Conferir o cabeçalho `Authorization` e a chave. |\n| 403 | A chave não pode fazer isto: restrita a outra empresa (`acesso_negado`, `chave_restrita`) ou chave de teste numa operação só de produção. | Usar a chave certa. |\n| 404 | Não existe nesta conta e neste ambiente. | Conferir o id e o ambiente da chave. |\n| 409 | Conflito: `referencia_duplicada`, `idempotencia_conflito`, `conflito`, `referencia_ambigua`, estado que não permite a operação. | Ler `codigo`. Ver [Idempotência](#tag/idempotência). |\n| 410 | `cursor_vencido` em `/v1/eventos`. | Continuar de `cursor_mais_antigo`. |\n| 412 | `empresa_nao_pronta`: a empresa não pode emitir. Nada foi criado. | Resolver os itens em `bloqueio` de `itens`. Ver [Prontidão](#tag/prontidão). |\n| 413 | Planilha acima de 20 MB em `POST /v1/lotes`. | Dividir a planilha. |\n| 422 | O pedido foi entendido e recusado: `validacao`, `nfse_rejeitada`, `falha_transmissao`, `cancelamento_recusado`... | Ler `codigo`, `erros`, `correcao`. |\n| 429 | Mais de 120 requisições no minuto, nesta chave. | Esperar a virada do minuto e repetir. |\n| 500 | Erro nosso (`erro_interno`, `retentavel: true`). | Repetir com a mesma `Idempotency-Key`. Se persistir, mande o `X-Request-Id` ao suporte. |\n\nO 429 também tem os dois formatos: problem+json `limite_de_requisicoes`\n(`retentavel: true`) nas rotas de emissão, lote, webhooks e eventos, e\n`{\"message\": \"...\", \"code\": \"RATE_LIMITED\"}` nas demais. Não há cabeçalho\n`Retry-After` nem `X-RateLimit-*`.\n\n### Códigos (`codigo`) das rotas problem+json\n\n| `codigo` | Status | Quando |\n|---|---|---|\n| `parametro_invalido` | 400 | Filtro, data, `limite` ou `cursor` inválido |\n| `requisicao_invalida` | 400 | Pedido malformado |\n| `nao_autenticado` | 401 | Chave ausente, inválida ou revogada |\n| `acesso_negado` | 403 | Chave restrita a outra empresa |\n| `chave_restrita` | 403 | Chave restrita a uma empresa tentando administrar webhooks |\n| `nao_encontrado` | 404 | Empresa inexistente, ou nota ainda sem XML |\n| `nfse_nao_encontrada` | 404 | Nenhuma nota com esse id, referência ou chave de acesso |\n| `lote_nao_encontrado` | 404 | Lote inexistente |\n| `empresa_nao_encontrada` | 404 | `empresa_id` inexistente em `POST /v1/lotes` |\n| `referencia_duplicada` | 409 | Já existe nota com essa `referencia` nesta empresa e ambiente |\n| `idempotencia_conflito` | 409 | Mesma `Idempotency-Key` com outro corpo |\n| `conflito` | 409 | A mesma `Idempotency-Key` ainda está em andamento |\n| `referencia_ambigua` | 409 | A `referencia` existe em mais de uma empresa: informe `empresa_id` |\n| `nfse_sem_pdf` | 409 | A nota ainda não tem PDF (`retentavel: true`) |\n| `nfse_nao_aguarda_confirmacao` | 409 | Confirmação de nota que não está em `aguardando_confirmacao` |\n| `lote_sem_emissao_manual`, `lote_validando`, `lote_ja_emitido` | 409 | `POST /v1/lotes/{id}/emissao` fora de hora |\n| `cursor_vencido` | 410 | Cursor de eventos mais velho que 90 dias |\n| `empresa_nao_pronta` | 412 | Prontidão com `bloqueio` |\n| `validacao` | 422 | Corpo inválido; os detalhes estão em `erros` |\n| `nfse_rejeitada` | 422 | O Sistema Nacional rejeitou a nota |\n| `falha_transmissao` | 422 | A transmissão não pôde ser concluída |\n| `cancelamento_recusado` | 422 | O Sistema Nacional recusou o cancelamento |\n| `planilha_obrigatoria` | 422 | `POST /v1/lotes` multipart sem o arquivo |\n| `simulacao_so_no_sandbox`, `simulacao_invalida` | 422 | Simulador com a chave de produção, ou cenário inexistente |\n| `reenvio_invalido`, `evento_nao_assinado` | 422 | Reenvio de webhook com parâmetros errados |\n| `limite_de_requisicoes` | 429 | Limite de requisições |\n| `erro_interno` | 500 | Erro nosso |\n\nDentro de `erros` (422 `validacao`) os códigos dizem qual campo e qual regra:\n`tipo_invalido`, `formato_invalido`, `campo_desconhecido`,\n`documento_invalido`, `referencia_muito_longa`, `tomador_igual_prestador`,\n`codigo_servico_inexistente`, `aliquota_iss_obrigatoria`,\n`competencia_invalida`, `obra_obrigatoria`, `nbs_fora_do_servico` e outros.\nCada um vem com `campo`, `mensagem` e `correcao`; trate qualquer código novo\npelo `campo` e pela `correcao`.\n\n### Rejeição do Sistema Nacional\n\nQuando o Sistema Nacional rejeita, o 422 `nfse_rejeitada` traz\n`codigo_oficial` (ex.: `E0039`) e a nota inteira em `nfse`. Em\n`nfse.rejeicao.explicacao`, para os códigos que a Sudrel conhece, vem a\nexplicação em português claro e a correção. A nota fica registrada como\n`rejeitada`: corrija e emita uma nota nova, com outra `referencia`.\n"
    },
    {
      "name": "Estados da NFS-e",
      "x-resumo": "Os 7 status de uma nota emitida, as transições, o que fazer em cada um e o webhook correspondente.",
      "description": "### Os 7 status de uma NFS-e emitida\n\n```text\n                     POST /v1/nfse\n                          |\n                          v\n                    transmitindo ----(30 min)----> aviso processamento_prolongado\n                     |   |    |                    (só aviso; o status não muda)\n                     |   |    +--(competência acabou num retry)--> aguardando_confirmacao\n                     |   |                                          |\n                     |   |              POST /v1/nfse/{id}/confirmacao\n                     |   |                                          |\n                     |   |    <-------------------------------------+\n                     |   |\n                     |   +--(recuperação desiste após 7 dias)--> falha_transmissao\n                     |\n         +-----------+-----------+\n         v                       v\n     autorizada              rejeitada\n         |\n         | cancelamento, ou substituição autorizada\n         v\n     cancelada\n```\n\n`descartada` não aparece no desenho: é a nota que voltou sem sucesso e foi\ndescartada no painel, ou a linha válida de um lote que você deixou de fora em\n`POST /v1/lotes/{id}/emissao`.\n\n| Status | O que significa | O que fazer | Final? | Webhook |\n|---|---|---|---|---|\n| `transmitindo` | Na fila, enviando, ou recuperando uma falha técnica do Sistema Nacional. | Esperar. **Não emita de novo.** | Não | Nenhum ao entrar. `NFSE_PROCESSAMENTO_PROLONGADO` aos 30 minutos, uma vez, como aviso. |\n| `autorizada` | NFS-e emitida. `numero` e `chave_acesso` preenchidos. | Baixar PDF e XML. | Sim (só pode virar `cancelada`) | `NFSE_AUTORIZADA` |\n| `rejeitada` | O Sistema Nacional recusou. Motivo em `rejeicao`. | Corrigir e emitir uma nota nova, com outra `referencia`. Em lote, `POST /v1/lotes/{id}/reprocessamento`. | Sim, pela API | `NFSE_REJEITADA` |\n| `cancelada` | Cancelada depois de autorizada. Protocolo em `cancelamento`. Se foi por substituição, `substituida_por` diz qual nota a substituiu. | Nada. | Sim | `NFSE_CANCELADA` |\n| `falha_transmissao` | A transmissão não pôde ser concluída nem confirmada, e nada mais será tentado sozinho. Veja `falha.dps_enviada`. | Com `\"nao\"`: emitir de novo é seguro. Com `\"desconhecido\"`: conferir no Emissor Nacional antes. | Sim | `NFSE_FALHA_TRANSMISSAO` |\n| `aguardando_confirmacao` | A competência da nota acabou antes de uma retentativa automática. Nada é transmitido até você decidir. | `POST /v1/nfse/{id}/confirmacao`, mantendo ou trocando a competência. | Não | `NFSE_AGUARDANDO_CONFIRMACAO` |\n| `descartada` | Descartada no painel, ou linha válida de lote que não foi escolhida. | Nada. | Sim | Nenhum |\n\nNão existe status `substituida`: a nota substituída fica `cancelada`, com\n`substituida_por`.\n\nA linha do tempo de cada nota está em `eventos`, no `GET /v1/nfse/{id}`:\n`criada`, cada `envio`, `consulta_dps`, `correcao_automatica`, `recuperada` e\nos demais passos, com a hora de cada um.\n\n### Por que a nota fica em `transmitindo`\n\nFalha técnica do Sistema Nacional (timeout, instabilidade) não volta como erro\npara você. A nota continua `transmitindo` enquanto a Sudrel recupera: antes\nde qualquer reenvio, consulta se a DPS já virou nota, então a mesma DPS nunca\ngera duas notas. Se a recuperação não conseguir em 7 dias, ou se não houver\ncomo consultar a DPS (por exemplo, nota emitida pelo sistema da prefeitura), a\nnota vai para `falha_transmissao`.\n"
    },
    {
      "name": "Prontidão",
      "x-resumo": "O que a empresa precisa ter para emitir, item por item, e o que bloqueia a emissão.",
      "description": "### Antes de emitir: consulte a prontidão\n\n`GET /v1/companies/{id}/prontidao` faz a mesma checagem que `POST /v1/nfse`\nfaz antes de criar a nota. Consultar antes evita descobrir o problema na hora\nde emitir, e diz o que corrigir.\n\nCada item vem com `situacao`, e a resposta inteira leva a pior delas:\n\n| `situacao` | Significa | Próximo passo |\n|---|---|---|\n| `ok` | Requisito atendido. | Emitir. |\n| `aviso` | Emite, mas vale olhar (certificado vencendo, parâmetro do município ainda desconhecido). | Emitir, e corrigir com calma. |\n| `bloqueio` | A emissão é recusada com **412** `empresa_nao_pronta`, sem criar nada. | Corrigir antes. Tentar emitir não adianta. |\n\n### Os itens\n\n| `item` | O que confere | Pode bloquear? |\n|---|---|---|\n| `certificado` | Certificado A1 presente e válido. Aviso nos últimos 30 dias. | Sim: ausente ou vencido |\n| `regime_tributario` | Regime tributário configurado. | Sim |\n| `plano_emissao` | Plano de Emissão ativo. Só em produção; no teste é sempre `ok`. | Sim |\n| `sandbox_municipio_proprio` | Só com a chave de teste: a empresa emite pelo sistema da prefeitura, que não tem ambiente de teste. | Sim |\n| `token_municipio` | Só quando a prefeitura autentica a emissão por um token gerado no portal dela (hoje, Eusébio-CE): o token está salvo. | Sim |\n| `regime_apuracao_simples` | Regime de apuração, no Simples Nacional. | Não |\n| `municipio_emissao` | Município da empresa conhecido. | Não |\n| `convenio_municipio` | Se o município usa o Sistema Nacional, e como. | Não |\n| `serie_dps` | Série da DPS. | Não |\n| `padroes_emissao` | Padrões da empresa (código de serviço etc.). | Não |\n| `parametros_municipais` | Parâmetros oficiais do município (alíquotas). | Não |\n| `nbs` | NBS para o IBS/CBS, quando ele vale para a empresa. | Não |\n| `reducao_ibs_cbs` | Redução de IBS/CBS prevista para o serviço. | Não |\n\nCada item traz `mensagem` e `correcao`, em português, com o que fazer. Novos\nitens podem aparecer: trate qualquer `item` desconhecido pela `situacao`.\n\nO webhook `EMPRESA_PRONTIDAO_ALTERADA` avisa quando um item muda de situação\n(conferido a cada 6 horas, só em produção). `POST /v1/nfse/validacoes` também\ndevolve a prontidão, junto da validação da nota.\n"
    },
    {
      "name": "Paginação e limites",
      "x-resumo": "Cursor de cada lista, limite de 120 requisições por minuto e tamanho máximo do corpo.",
      "description": "### Paginação por cursor\n\nAs listas que podem crescer usam cursor: você pede uma página, guarda o cursor\nque veio e o devolve para pedir a próxima. Os nomes mudam entre as rotas. É\nherança das duas partes do produto (documentos recebidos nasceram antes da\nemissão), e o contrato não muda, então confira a tabela:\n\n| Rota | Parâmetro do cursor | Itens em | Próximo cursor em | `limite` (padrão / máx.) |\n|---|---|---|---|---|\n| `GET /v1/documents` | `cursor` | `itens` | `proximoCursor` | 20 / 100 |\n| `GET /v1/nfse` | `cursor` | `dados` | `proximo_cursor` | 50 / 100 |\n| `GET /v1/lotes` | `cursor` | `dados` | `proximo_cursor` | 20 / 100 |\n| `GET /v1/lotes/{id}/itens` | `cursor` | `dados` | `proximo_cursor` | 100 / 500 |\n| `GET /v1/webhooks/{id}/entregas` | `cursor` | `entregas` | `proximo_cursor` | 50 / 200 |\n| `GET /v1/eventos` | `apos` | `eventos` | `proximo_cursor` | 100 / 1000 |\n\n`GET /v1/companies` e `GET /v1/webhooks` não são paginados: devolvem a lista\ninteira.\n\n**Regras que valem para todas:**\n\n- **Trate o cursor como valor opaco.** Guarde e devolva exatamente como veio.\n  Não interprete, não monte, não compare. O formato interno pode mudar.\n- **Termine quando o próximo cursor vier nulo.** Uma página com menos itens\n  que `limite`, ou até vazia, não quer dizer que acabou: com filtro de\n  `status`, a página pode vir menor e ainda ter próximo cursor.\n- **`GET /v1/eventos` é diferente:** o `proximo_cursor` vem sempre, mesmo na\n  página vazia. É um log que cresce: guarde o último cursor e volte a ler a\n  partir dele depois. Veja [Eventos](#tag/eventos).\n- Nas rotas de emissão, lote, webhooks e eventos, cursor inválido é 400\n  `parametro_invalido`. Em `/v1/eventos`, cursor mais\n  velho que a retenção de 90 dias é 410 `cursor_vencido`, com\n  `cursor_mais_antigo` para continuar.\n- `limite` fora da faixa: em `/v1/nfse` é ajustado para dentro dela, sem erro;\n  nas demais rotas é 400.\n\n### Limite de requisições\n\n120 requisições por minuto, por chave de API, em janela fixa de 60 segundos\nalinhada ao relógio. Passar do limite devolve **429**. Não há cabeçalho\n`Retry-After` nem `X-RateLimit-*`: espere a virada do minuto e repita a mesma\nrequisição.\n\n- Um `POST /v1/lotes` conta como **uma** chamada, qualquer que seja o número\n  de itens. Para volume, use lote.\n- Para acompanhar notas, use webhook. Consultar uma nota a cada segundo gasta\n  o limite sem adiantar nada.\n\n### Tamanho do corpo\n\nAté 2 MB por requisição. `POST /v1/lotes` aceita até 30 MB em JSON e planilha\nde até 20 MB.\n"
    },
    {
      "name": "Conta",
      "x-resumo": "Dados da conta e consumo do ciclo atual.",
      "description": "Informações da sua conta e do consumo no ciclo atual de Recebidas. A\nchave de teste também lê estas rotas. Erros no formato NestJS (veja\n[Erros e status HTTP](#tag/erros-e-status-http)).\n"
    },
    {
      "name": "Empresas",
      "x-resumo": "Cadastro de CNPJs, certificado A1, pausa, remoção e prontidão para emitir.",
      "description": "CNPJs da conta: cadastro, certificado A1, pausa, remoção e a\n[prontidão](#tag/prontidão) para emitir. A chave de teste lê as empresas, mas\nnão cria nem altera (403). O `id` de cada empresa é o `empresa_id` das rotas\nde emissão. Erros no formato NestJS (veja\n[Erros e status HTTP](#tag/erros-e-status-http)).\n"
    },
    {
      "name": "Documentos",
      "x-resumo": "NFS-e, NF-e e CT-e recebidos e emitidos pelas empresas, com eventos e manifestações.",
      "description": "NFS-e, NF-e e CT-e em que a empresa é tomadora (`RECEBIDA`) ou prestadora\n(`EMITIDA`), capturados do Ambiente de Dados Nacional e da SEFAZ, com os\neventos de cada um (cancelamento, substituição, manifestação). Só com chave de\nprodução: a de teste recebe 403.\n\nA lista é paginada por cursor (`cursor` e `proximoCursor`, em camelCase como o\nresto destas rotas). Para manter um sistema sincronizado, veja a receita\n\"Sincronizar documentos recebidos\" em [Receitas](#tag/receitas).\n"
    },
    {
      "name": "Emissão de NFS-e",
      "x-resumo": "Emitir, validar, consultar, cancelar e substituir NFS-e, com ajustes automáticos por município.",
      "description": "Emita NFS-e pelo mesmo motor da planilha e do painel: mesma validação,\nmesma fila, mesma recuperação de falha técnica. A nota emitida pela API\naparece no painel, com a origem \"API\".\n\n**Você manda sempre o mesmo JSON, qualquer que seja o município.** O\nque muda por município ou por cenário tributário (preencher, omitir,\nexigir um campo) é decidido do nosso lado, e a resposta conta o que foi\nfeito em `ajustes`:\n\n```json\n{\n  \"campo\": \"/prestador/inscricao_municipal\",\n  \"acao\": \"omitido\",\n  \"motivo\": \"O município não aceita a inscrição municipal do prestador nesta DPS (E0120). A nota foi reenviada sem ela.\",\n  \"regra\": \"correcao.E0120\"\n}\n```\n\n`acao` é `preenchido`, `omitido`, `derivado` ou `exigido`; `regra` é o\nidentificador estável da regra no nosso catálogo (por exemplo\n`dps.pAliq.exigido.simples_retido`, `param.aliquota_iss`,\n`correcao.E0120`). `regras_versao` traz a versão dos dois catálogos que\ndecidiram a nota, correção automática e regras de campo, nessa ordem\n(`2026-09-30.1+2026-10-02.1`).\n\nQuando a alíquota do ISS é obrigatória e você não manda nenhuma (nem a\nempresa tem uma padrão), usamos a alíquota OFICIAL que o município\ncadastrou no Sistema Nacional para o serviço, se ela for única na\ncompetência. Aparece como ajuste `preenchido` com regra\n`param.aliquota_iss`.\n\n### Status\n\nO ciclo completo, com o que fazer em cada um e o webhook correspondente, está\nem [Estados da NFS-e](#tag/estados-da-nfs-e).\n\n| Status | O que significa |\n|---|---|\n| `transmitindo` | Estamos cuidando: na fila, enviando, ou recuperando uma falha técnica do Sistema Nacional. Não reenvie. |\n| `autorizada` | NFS-e emitida. `numero` e `chave_acesso` preenchidos. |\n| `rejeitada` | O Sistema Nacional recusou. Motivo em `rejeicao`. Corrija e emita uma nota nova. |\n| `cancelada` | Cancelada depois de autorizada. Protocolo em `cancelamento`. Se foi por substituição, `substituida_por` diz qual nota a substituiu. |\n| `falha_transmissao` | Final. A transmissão não pôde ser concluída nem confirmada, e nada mais será tentado automaticamente. Veja `falha`: com `dps_enviada: \"desconhecido\"`, confira no Emissor Nacional antes de emitir de novo. |\n| `descartada` | A nota voltou sem sucesso e foi descartada no painel. |\n| `aguardando_confirmacao` | A competência da nota acabou antes de uma retentativa automática. Nada é transmitido até você confirmar em `POST /v1/nfse/{id}/confirmacao` (pode trocar a competência). |\n\nSe a nota passar 30 minutos em `transmitindo`, a resposta ganha\n`aviso: {\"codigo\": \"processamento_prolongado\"}` e sai o webhook\n`NFSE_PROCESSAMENTO_PROLONGADO`, uma vez. É só aviso: a nota continua\nsendo cuidada e o status não muda.\n\n### Substituir uma NFS-e\n\nPara corrigir uma nota autorizada sem cancelar e emitir outra, emita a\nnota certa em `POST /v1/nfse` com o bloco `substituicao`:\n\n```json\n{\n  \"empresa_id\": \"…\",\n  \"tomador\": { \"documento\": \"11222333000181\" },\n  \"valor\": \"1500.00\",\n  \"servico\": { \"descricao\": \"Consultoria de setembro, valor corrigido\" },\n  \"substituicao\": { \"nfse_id\": \"id-da-nota-original\", \"codigo_motivo\": \"99\", \"motivo\": \"Valor do serviço informado errado na nota original.\" }\n}\n```\n\nA nota nova segue o caminho de sempre. Quando ela é autorizada, o\nSistema Nacional cancela a original sozinho (cancelamento por\nsubstituição): a original passa a `cancelada`, com `substituida_por`, e\nsai o webhook `NFSE_CANCELADA` dela. Se a nova for rejeitada, a original\ncontinua autorizada e nada muda nela.\n\nAntes de transmitir, recusamos com 422 o que já se sabe que não passa:\nnota cancelada ou já substituída (E0046), nota de outro ambiente\n(E0065), outra substituição da mesma nota em andamento, e `codigo_motivo`\n99 sem `motivo` (E0078). O prazo de substituição do município (E0050) e a\nmanifestação do tomador (E0070) só o Sistema Nacional sabe; voltam como\nrejeição, com `rejeicao.explicacao`.\n\nPara NFS-e emitida fora da Sudrel, use `chave_acesso` no lugar de\n`nfse_id`. A substituição não existe por lote.\n\n### Construção civil: dados da obra\n\nNos códigos de construção civil (07.02.01, 07.02.02, 07.04.01, 07.05.01,\n07.05.02, 07.06.01, 07.06.02, 07.07.01, 07.08.01, 07.17.01, 07.19.01,\n14.14.03 e 14.14.04) o Sistema Nacional exige os dados da obra, e nos\ndemais recusa. Mande `servico.obra` com o CNO, o CIB ou o CEP e número\ndo endereço da obra, e o município, quando ele não vem do CEP:\n\n```json\n{ \"servico\": { \"codigo_nacional\": \"070201\", \"obra\": { \"cno\": \"90.012.34567/89\", \"municipio\": \"Lauro de Freitas - BA\" } } }\n```\n\nO município da obra vira o local da prestação da nota. Nos códigos em\nque o ISS é devido onde a obra fica, é o convênio desse município que\ndecide se a alíquota do ISS é exigida. Na planilha, são as colunas \"CNO\nda obra\", \"CEP da obra\" etc., no layout Completo.\n\n### Testando a integração (sandbox)\n\nUse uma chave `sdr_test_` nas MESMAS rotas e com o MESMO JSON. A nota é\ntransmitida de verdade ao ambiente de testes do Sistema Nacional\n(produção restrita), com o certificado real da empresa, e volta\nautorizada ou rejeitada pelas mesmas regras. Ela não tem valor fiscal,\nnão conta na franquia, não depende de plano e não aparece no painel.\n`ambiente` vem `sandbox` na resposta e nos webhooks.\n\nOs dois ambientes nunca se cruzam: a chave de teste só enxerga notas de\nteste, a de produção só as de produção, e a mesma `referencia` ou\n`Idempotency-Key` pode ser usada nos dois. Empresa que emite pelo\nsistema do próprio município não tem ambiente de teste: a prontidão traz o\nitem `sandbox_municipio_proprio` em `bloqueio`, e a emissão é recusada com 412\n`empresa_nao_pronta`.\n\nFalha técnica do Sistema Nacional não é resposta pra você: a nota\ncontinua `transmitindo` enquanto a recuperação automática trabalha\n(ela consulta a DPS antes de qualquer reenvio, então a nota nunca é\nemitida duas vezes).\n\n### Emissão mínima\n\n```bash\ncurl https://api.sudrel.com.br/api/v1/nfse \\\n  -H \"Authorization: Bearer sdr_live_...\" \\\n  -H \"Idempotency-Key: 7f1c0d9a-4a51-4e0e-9b1f-2b6f0d3c5a10\" \\\n  -H \"Prefer: wait=15\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"empresa_id\":\"0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00\",\"referencia\":\"PED-1001\",\"tomador\":{\"documento\":\"11222333000181\"},\"valor\":\"1500.00\",\"servico\":{\"descricao\":\"Consultoria em sistemas\"}}'\n```\n\nValores em dinheiro e alíquotas vão como TEXTO com ponto decimal\n(`\"1500.00\"`). Número JSON é recusado, pra nenhum valor de nota fiscal\ndepender de arredondamento de ponto flutuante.\n"
    },
    {
      "name": "Emissão em lote",
      "x-resumo": "Até 5.000 notas numa chamada, por JSON ou planilha, com resultado e reprocessamento por linha.",
      "description": "Até 5.000 notas numa chamada, por JSON ou pela planilha do painel, com\nresultado por linha. Mesmo motor da emissão avulsa e da planilha. Mande\nsempre `referencia` em cada item: é o que torna seguro reenviar o lote.\n\n```text\nPOST /v1/lotes  --202-->  validando\n                              |\n          ao_validar = emitir_validas          ao_validar = aguardar\n                              |                       |\n                              |               aguardando_emissao\n                              |                       |\n                              |          POST /v1/lotes/{id}/emissao\n                              v                       v\n                          processando  (as notas transmitindo)\n                              |\n                              v\n                          concluido  --> webhook LOTE_EMISSAO_CONCLUIDO\n```\n\n| Etapa | Rota | O que acontece |\n|---|---|---|\n| Criar | `POST /v1/lotes` | Sempre 202. Prontidão com `bloqueio` é 412, e nada é criado. |\n| Acompanhar | `GET /v1/lotes/{id}` | `status`: `validando`, `aguardando_emissao`, `processando`, `concluido` ou `erro`, e as contagens. |\n| Resultado por linha | `GET /v1/lotes/{id}/itens` | Cada linha com o status da nota, ou `com_erro_validacao`, `aguardando_emissao`, `ja_existente`. |\n| Emitir (com `aguardar`) | `POST /v1/lotes/{id}/emissao` | `\"todas\"` ou uma lista de linhas. Uma vez só. |\n| Corrigir e emitir de novo | `POST /v1/lotes/{id}/reprocessamento` | Só linhas com erro, `rejeitada` ou `falha_transmissao` com `dps_enviada: \"nao\"`. |\n| Relatório | `GET /v1/lotes/{id}/relatorio` | A planilha com o resultado de cada linha. |\n\n**Limites:** 5.000 itens com a chave de produção, 100 com a de teste. JSON\naté 30 MB, planilha até 20 MB. Um `POST /v1/lotes` conta como uma chamada no\nlimite de requisições. Itens de lote entram na fila atrás das notas avulsas.\n\n**Não confunda validar com emitir.** A validação roda sempre, logo depois de\ncriar o lote. Com `emitir_validas` (padrão), as linhas válidas são emitidas em\nseguida. Com `aguardar`, nada é emitido até você chamar\n`POST /v1/lotes/{id}/emissao`.\n\nMande `referencia` em todo item: é o que torna seguro mandar o lote de novo.\nVeja [Idempotência](#tag/idempotência).\n"
    },
    {
      "name": "Emissão de NF-e",
      "x-resumo": "Emitir, validar, consultar, cancelar e corrigir NF-e modelo 55, com os tributos vindos do seu ERP.",
      "description": "Emita NF-e (modelo 55) com as mesmas convenções da NFS-e: `Idempotency-Key`,\n`referencia` única por empresa, `Prefer: wait`, erros em Problem Details,\n`ajustes`, `regras_versao`, cursor de eventos e webhooks assinados. Quem já\nintegrou NFS-e não reaprende nada.\n\n**Três modos, escolhidos em `modo`:**\n\n- `informado` (padrão): os tributos vêm prontos do seu ERP. Você manda, em cada\n  item, os grupos de ICMS, IPI, PIS, COFINS e IBS/CBS já calculados; a Sudrel\n  confere os totais contra a soma dos itens, valida no esquema oficial da SEFAZ\n  antes de assinar, assina com o certificado A1 da empresa, transmite e acompanha.\n- `calcular`: cada item traz só `produto` (o código cadastrado em `/v1/produtos`),\n  quantidade e valor; o motor fiscal da Sudrel resolve CFOP e tributos e explica\n  cada valor em `ajustes` (regra, versão e fonte legal). Veja **Produtos e motor\n  fiscal**.\n- `conferir`: você manda os valores, como no informado, mais o `produto` de cada\n  item; a Sudrel calcula ao lado e devolve as diferenças em `ajustes`.\n\n**Uma nota nunca vira duas.** A chave de acesso é gravada antes do envio. Se a\nresposta da SEFAZ não chega (timeout, queda), a nota fica\n`aguardando_confirmacao` e a Sudrel consulta a chave na SEFAZ: só reenvia, e o\nMESMO XML, se a SEFAZ disser que a nota não existe. Duplicidade (204) não é\nerro para você: a consulta resolve.\n\n### O que é obrigatório\n\n| Campo | Modo `informado` | Modo `calcular` |\n|---|---|---|\n| `empresa_id` | Sim (dispensado com chave restrita a uma empresa) | Igual |\n| `referencia` | Não, mas mande: é por ela que você consulta e evita nota dobrada | Igual |\n| `natureza_operacao` | Sim | Não: vem do catálogo de operações |\n| `presenca` | Sim | Sim |\n| `destinatario.documento` | Sim | Sim |\n| `destinatario.nome` | Com CPF. Com CNPJ, vem da Receita | Igual |\n| `destinatario.endereco` | Com CPF, só `cep` e `numero`. Com CNPJ, vem da Receita | Igual |\n| `destinatario.inscricao_estadual` | Só com `contribuinte: \"contribuinte\"`. Sem `contribuinte`, a Sudrel consulta a SEFAZ | Igual |\n| Item | `codigo`, `descricao`, `ncm`, `cfop`, `origem`, `unidade`, `quantidade`, `valor_unitario`, `icms`, `pis` e `cofins` | `produto`, `quantidade` e `valor_unitario` |\n| `pagamentos` | Ao menos um, com `forma` e `valor` (`descricao` na forma `outros`) | Ao menos um; se for um só, o `valor` pode faltar (vira o valor da nota) |\n| `totais` | Não: somados dos itens | Não |\n\nConforme a `operacao` (modos `calcular` e `conferir`; no informado, o CFOP e a\n`finalidade` que você manda já dizem a operação):\n\n| `operacao` | Exige a mais | Tributos |\n|---|---|---|\n| `venda` (padrão), `venda_consumidor_final`, `bonificacao` | Nada | Calculados |\n| `remessa` | `subtipo`: `conserto`, `demonstracao`, `industrializacao` ou `outras` | No modo informado: o catálogo resolve CFOP e natureza, o motor não calcula remessa |\n| `transferencia` | Nada | No modo informado |\n| `devolucao` | `chave_referenciada` (44 caracteres) e `subtipo` `comercializacao` (padrão) ou `industrializacao` | No modo informado: mande a mesma `chave_referenciada` e `finalidade: \"devolucao\"`, com os tributos da nota de origem. No `conferir`, a nota segue com os seus valores, sem conferência |\n\nNo modo informado, a `finalidade` decide se a nota de origem é obrigatória:\n`devolucao` e `complementar` exigem `chave_referenciada` (sem ela, 422\n`chave_referenciada_obrigatoria`); `normal` e `ajuste` aceitam, sem exigir. A\nSudrel confere o tamanho e o dígito verificador antes de enviar e põe a chave\nonde a SEFAZ pede: na devolução, em cada item (`det/DFeReferenciado`, com o\n`item_referenciado` quando você informa); nas outras finalidades, na nota\n(`NFref/refNFe`). As duas juntas a SEFAZ recusa (rejeição 1010).\n\nO que falta ou está errado volta junto, num 422 `validacao`, cada erro com o\n`campo` (JSON Pointer), a `mensagem` e a `correcao`.\n\n### Sandbox e produção\n\n- Chave `sdr_test_`: emite **de verdade na homologação da SEFAZ** (tpAmb 2),\n  com o certificado real da empresa, sem valor fiscal e sem cobrança, em\n  qualquer UF. O nome do destinatário sai como a SEFAZ exige em homologação.\n- Chave `sdr_live_`: emite na produção da SEFAZ (tpAmb 1), com valor fiscal.\n  O pedido, a resposta e os webhooks são os mesmos da homologação.\n\n### Status\n\n| Status | O que significa |\n|---|---|\n| `transmitindo` | Estamos cuidando: na fila ou enviando. Não reenvie. |\n| `aguardando_confirmacao` | A nota foi enviada e a resposta da SEFAZ não chegou. A Sudrel está consultando a chave; nenhuma nota nova é criada e você não precisa fazer nada. |\n| `autorizada` | NF-e autorizada. `protocolo`, `chave_acesso`, XML e DANFE disponíveis. |\n| `rejeitada` | A SEFAZ recusou. `rejeicao` traz o `cStat`, a mensagem da SEFAZ e, quando conhecida, a explicação em português. O número continua seu: corrija por `POST /v1/nfe/{id}/correcao`. |\n| `denegada` | Uso denegado pela SEFAZ (irregularidade fiscal). O número foi consumido e a nota não pode ser usada. |\n| `cancelada` | Cancelada depois de autorizada. Protocolo em `cancelamento`. |\n| `descartada` | Você desistiu da nota (ou a Sudrel descartou uma rejeitada esquecida). O número é inutilizado. |\n| `contingencia_epec` | A SEFAZ da UF estava fora e a nota entrou em contingência por EPEC: o evento foi registrado no Ambiente Nacional e o DANFE já vale. A NF-e vai à UF quando ela voltar (veja **Contingência da NF-e**). |\n\nEquivalência com o status interno: `PENDENTE` e `TRANSMITINDO` são\n`transmitindo`; `AGUARDANDO_CONFIRMACAO`, `AUTORIZADA`, `DENEGADA`, `REJEITADA`,\n`DESCARTADA` e `CANCELADA` têm o mesmo nome em minúsculas; `EPEC_REGISTRADO` é\n`contingencia_epec`. Na NFS-e,\n`aguardando_confirmacao` pede a sua confirmação; na NF-e, é a Sudrel\nconfirmando com a SEFAZ.\n\n### O que a Sudrel preenche (`ajustes`)\n\n| `regra` | O que foi feito |\n|---|---|\n| `nfe_modo_informado` | Sem `modo`: tributos informados por você. |\n| `nfe_serie_da_origem` | Sem `serie`: a série da API desta empresa (cada canal tem a sua). |\n| `nfe_destino_operacao` | Operação interna, interestadual ou com o exterior, pelas UFs. |\n| `nfe_totais_somados` | Totais que você não mandou, somados dos itens. |\n| `nfe_valor_total_item` | Valor do item: quantidade vezes valor unitário. |\n| `nfe_sem_gtin` | Produto sem código de barras: \"SEM GTIN\". |\n| `nfe_transporte_sem_frete` | Sem transporte: \"sem frete\". |\n| `nfe_tipo_operacao_saida` | Sem `tipo_operacao`: saída. |\n| `nfe_finalidade_normal` | Sem `finalidade`: NF-e normal. |\n| `nfe_ibs_soma_uf_municipio` | IBS do item: soma da parcela da UF com a do município. |\n| `nfe_totais_ibs_cbs_somados` | Totais de IBS e CBS que você não mandou, somados dos itens. |\n| `nfe_correcao_<cStat>` | Correção automática feita depois de uma rejeição conhecida. |\n| `nfe_destinatario_homologacao` | No sandbox, o nome do destinatário é a literal da SEFAZ. |\n| `nfe_autxml_escritorio` | Na BA, o escritório de contabilidade da empresa no grupo autXML (exigência da UF). |\n| `nfe_autxml_sefaz_sem_escritorio` | Na BA, sem escritório vinculado: o CNPJ da SEFAZ-BA. |\n| `nfe_autxml_sefaz_apos_487` | A SEFAZ recusou o escritório (487); a nota foi refeita com o CNPJ da SEFAZ. |\n| `nfe_indintermed_padrao` | Indicativo de intermediador \"sem intermediador\", quando a presença exige. |\n| `nfe_autxml_sefaz_escritorio_recusado` | A SEFAZ já tinha recusado o escritório desta empresa (487): a nota saiu direto com o CNPJ da SEFAZ, sem uma ida rejeitada. |\n| `nfe_operacao_venda` | Modos calcular e conferir, sem `operacao`: venda. |\n| `nfe_natureza_da_operacao` | Natureza da operação do catálogo de operações. |\n| `nfe_pagamento_valor_da_nota` | Modo calcular, um pagamento sem valor: o valor da nota calculada. |\n| `nfe_conferencia_divergencia` | Modo conferir: o valor informado difere do calculado (`acao: \"divergente\"`). |\n| `nfe_conferencia_fora_de_cobertura` | Modo conferir: o item não foi conferido porque está fora da cobertura do motor. |\n\nNo modo `calcular`, cada valor calculado entra em `ajustes` com `acao: \"calculado\"`,\na `regra` (por exemplo `icms_ba_ai_geral_2024`, `ipi_aliquota_tipi`,\n`pis_cofins_base_sem_icms`, `ibs_cbs_calculadora_oficial`), o `valor`, a `versao`\nda regra ou da tabela e a `fonte` legal.\n\n### Cancelamento e carta de correção\n\nCancelamento até **24 horas** depois da autorização (regra nacional). Fora do\nprazo, a resposta é 422 `cancelamento_fora_do_prazo`: só resta o cancelamento\nextemporâneo, pedido pelo contribuinte na SEFAZ. **Na Bahia não existe\ncancelamento extemporâneo** (RICMS/BA, art. 92): se a mercadoria não circulou, o\ncaminho é uma NF-e de entrada ou saída de regularização em até 60 dias, com a\nchave da nota incorreta referenciada; a resposta do 422 já diz isso. A carta de correção (até 20 por\nnota) **não corrige** valores, quantidade, base de cálculo, alíquota, dados que\nmudem o remetente ou o destinatário, nem a data de emissão ou de saída. A Sudrel\nnão lê o texto: a resposta traz esse aviso, sem bloquear.\n\n### Numeração\n\nCada canal (API, planilha, painel) tem a sua série, e o número só é reservado\nquando a nota é criada (validação e prévia nunca reservam). Rejeitada esquecida\nvira `descartada` sozinha antes do prazo legal de inutilização, com o webhook\n`NFE_DESCARTE_PROXIMO` alguns dias antes. A Sudrel inutiliza sozinha os números\nque ela mesma perdeu; `GET /v1/nfe/inutilizacoes` mostra o que foi inutilizado e\npor quê.\n"
    },
    {
      "name": "Produtos e motor fiscal",
      "x-resumo": "Cadastro de produtos validado na tabela oficial e o cálculo dos tributos da NF-e com regra e fonte de cada valor.",
      "description": "### Cadastro de produtos\n\n`POST /v1/produtos` cadastra o produto da empresa com o seu código (SKU). A\nvalidação acontece no cadastro, não na nota:\n\n| Recusa | Tabela oficial |\n|---|---|\n| `ncm_inexistente`, `ncm_fora_de_vigencia` | Nomenclatura vigente do Siscomex (Resolução Gecex nº 926/2026) |\n| `cest_inexistente`, `cest_incompativel_ncm` | Convênio ICMS 142/18, texto consolidado do CONFAZ |\n| `gtin_invalido`, `gtin_digito_invalido`, `gtin_prefixo_invalido` | Regras GS1 de dígito verificador e prefixos reservados |\n\nA homologação da SEFAZ chega a autorizar NCM inexistente; a produção recusa a\nnota. Por isso o cadastro confere antes. Cada tabela vem de fonte oficial, com a\ndata da cópia e o SHA-256 do arquivo de origem.\n\nO GTIN também é consultado no Cadastro Centralizado de GTIN da SEFAZ, com o\ncertificado da empresa: se a SEFAZ conhece o GTIN com outro NCM, o cadastro é\nrecusado com `gtin_ncm_divergente`. O que a SEFAZ devolveu fica em `gtin_sefaz`.\nGTIN que a SEFAZ não conhece, ou consulta fora do ar, não impede o cadastro.\n\nA nota guarda uma cópia do produto como ele estava na emissão: mudar o produto\ndepois não muda nota emitida.\n\n### Perfil fiscal e aprovação\n\nO perfil fiscal do produto diz o tratamento de ICMS (`tributado`,\n`base_reduzida`, `isento`, `nao_tributado`, `imune`, `st_retida`, `st_substituto`), o de PIS/COFINS\n(`tributado`, `monofasico`, `aliquota_zero`, `outros`) e o CST e a classificação do\nIBS/CBS. O da empresa (`PUT /v1/nfe/perfil-fiscal/{empresa_id}`) diz o regime de\nPIS/COFINS, se ela é contribuinte do IPI e, no Simples, a alíquota de crédito do\nmês (CSOSN 101). **Nada é calculado sem perfil aprovado por uma pessoa** da empresa\nou do escritório: `POST /v1/produtos/{codigo}/aprovacao-perfil` e\n`POST /v1/nfe/perfil-fiscal/{empresa_id}/aprovacao` gravam quem aprovou e quando.\nMudar um campo fiscal apaga a aprovação.\n\n**Sandbox com cadastro próprio.** A chave `sdr_test_` cadastra, altera e aprova\nprodutos e perfis num cadastro separado, só dela: nada do que ela grava aparece\npara a chave de produção, e ela não vê nem muda o cadastro de produção. Assim dá\npara testar o modo calcular inteiro sem tocar no que emite de verdade. O campo\n`ambiente` do produto diz de qual cadastro ele é.\n\n### Termo de Acordo de atacadista (Bahia)\n\nPara o atacadista credenciado no Decreto 7.799/2000, grave o credenciamento no\nperfil da empresa (`termo_acordo` com número, item do Anexo Único e vigência) e\nmarque `termo_acordo: true` nos produtos alcançados. O motor aplica a redução de\n41,176% da base (CST 20) só onde o decreto alcança: vigência do credenciamento,\nsaída interna para contribuinte inscrito na Bahia ou pessoa jurídica não\ncontribuinte (art. 1º e §3º), venda ou bonificação, mercadoria na alíquota geral\n(art. 5º), sem ST (art. 4º), fora do papel higiênico (art. 2º-A). Fora disso, a\nnota sai sem a redução e o motivo vem em `ajustes` (`termo_acordo_nao_aplicado`).\nAs condições de período (percentual de saídas para contribuintes, faturamento,\ntransferências) são do credenciamento: quem aprova o perfil declara que valem.\n\n### ICMS-ST\n\n- **Revenda com ST retida anteriormente** (CST 60 / CSOSN 500): os campos de ST\n  retida saem das notas de compra que a Sudrel já captura, pelo vínculo do produto\n  com o item de compra (`POST /v1/produtos/{codigo}/vinculos-entrada`, por GTIN,\n  pelo código do fornecedor ou manual), das últimas aquisições e proporcionais à\n  quantidade que sai (Convênio ICMS 142/18, cláusula décima quinta, §3º). Sem\n  vínculo, mande `st_retido` no item; sem nenhum dos dois, a nota sai como você\n  informar, com aviso em `ajustes`.\n- **Substituto na venda interna** (`st_substituto`): ICMS10 (ou ICMS70 com\n  redução), MVA do Anexo 1 do RICMS/BA e alíquota interna. Venda a consumidor\n  final não tem operação subsequente e sai como ICMS00. Item do Anexo 1 que pede\n  conferência, com FECP ou com MVA ajustada fica fora da cobertura.\n- ST interestadual fica fora da cobertura.\n\n### 7% para ME/EPP (Bahia)\n\nNa venda interna do fabricante para ME ou EPP optante do Simples inscrita na\nBahia, a alíquota é 7% e o benefício vai como desconto expresso na nota (Lei\n7.014/96, art. 16, I, \"c\", e §1º): o motor calcula o desconto, põe em `vDesc` e\nexplica em `infAdProd`. O porte do destinatário vem do que você informar em\n`destinatario.optante_simples`; sem isso, da consulta de CNPJ, com a fonte em\n`ajustes` (`nfe_destinatario_porte_consulta_cnpj`). O que você informa prevalece.\n\n### PIS/COFINS e o ICMS na base\n\nO perfil da empresa tem `exclui_icms_base_pis_cofins` (padrão `true`, Tema 69 do\nSTF): a base do PIS/COFINS sai sem o ICMS destacado e, na revenda com ST, sem o\nICMS-ST retido. Com `false`, o ICMS fica na base, que é a escolha conservadora de\nquem ainda não aplica a exclusão.\n\n### Operações\n\n`operacao` resolve CFOP, finalidade e natureza: `venda`,\n`venda_consumidor_final`, `remessa` (com `subtipo`: `conserto`, `demonstracao`,\n`industrializacao` ou `outras`), `transferencia`, `bonificacao` e `devolucao` (com\n`chave_referenciada` e `subtipo` `comercializacao` ou `industrializacao`).\n\n### O que o motor calcula\n\n| Tributo | Cobertura |\n|---|---|\n| ICMS | Emitente na Bahia. Operação interna, ou interestadual com destinatário contribuinte (12%, ou 4% para importados). Simples: CSOSN 101 (com o crédito do mês), 102, 103, 300 e 500 (com a ST retida das entradas). Regime normal: CST 00, 20 (reduções objetivas da base legal da BA e Termo de Acordo de atacadista), 40, 41, 60 (com a ST retida das entradas), 10 e 70 (ST do substituto na venda interna) e 7% para ME/EPP, com o FECP da BA. |\n| IPI | Contribuinte do IPI, produção própria, alíquota da TIPI. No Simples, sem destaque. |\n| PIS/COFINS | Regime cumulativo ou não cumulativo, base sem o ICMS destacado (ou com, pelo perfil da empresa) e sem o ICMS-ST retido; alíquota zero. No Simples, CST 49 sem destaque. |\n| IBS/CBS | Regime normal, pela calculadora oficial da Receita. |\n\n**Nunca um valor chutado.** O que está fora da cobertura responde 422\n`fora_de_cobertura`, com a lista `fora_de_cobertura` (item, tributo e motivo), e a\nnota pode seguir no modo informado. Exemplos: ST interestadual, DIFAL, emitente\nfora da BA, venda interna do fabricante para contribuinte cujo porte nem você nem\na consulta de CNPJ informaram (a Bahia tem 7% para ME/EPP), PIS/COFINS de\nrevenda com ICMS-ST sem o valor retido nas entradas e monofásico.\nSe a calculadora oficial do IBS/CBS não responder, o `fora_de_cobertura` vem com\n`temporario: true` e `retentavel: true`: tente de novo.\n\n### Modo conferir\n\nA nota sai com os SEUS valores, e cada diferença volta em `ajustes` com\n`acao: \"divergente\"` e a regra `nfe_conferencia_divergencia`. Com\n`recusar_divergencias: true` no perfil da empresa, a nota com diferença é recusada\ncom 422 `conferencia_divergente` e a lista `divergencias`.\n"
    },
    {
      "name": "NF-e pela planilha e em lote",
      "x-resumo": "A planilha Básica de NF-e (uma linha por produto), a de produtos, e o lote com tipo nfe.",
      "description": "Para quem não integra: a NF-e pela planilha, no painel ou por `POST /v1/lotes`\ncom `\"tipo\": \"nfe\"`. A planilha não tem caminho próprio: cada nota vira o corpo\nde `POST /v1/nfe` no modo `calcular`, e o resultado por linha é o mesmo pelo\npainel e pela API.\n\n### 1. Produtos, uma vez só\n\nA planilha de notas cita o produto **só pelo código**. Produto novo entra pela\nplanilha de produtos (ou `POST /v1/produtos`), com as mesmas validações: NCM,\nCEST e GTIN recusados na linha, com o motivo.\n\n| Coluna | Observação |\n|---|---|\n| Código | O código que vai na planilha de notas. |\n| Descrição, NCM, Unidade | Obrigatórias. |\n| Origem | Em branco: 0 (nacional). |\n| GTIN, CEST | Opcionais. |\n| Perfil fiscal | O nome de um perfil já aprovado da empresa (`perfil_fiscal_nome`). |\n\n### 2. A planilha de notas (Básica)\n\nUma linha por **produto**. As linhas com o mesmo número na coluna **Nota** (1, 1,\n2...) viram uma NF-e só. Dado da nota (destinatário, pagamento) pode ficar em\nbranco nas linhas seguintes; valor diferente na mesma nota põe a nota inteira em\nerro, explicando as duas linhas.\n\n| Coluna | Na API |\n|---|---|\n| Nota | Agrupa as linhas (não vai para a API). |\n| CPF ou CNPJ do destinatário | `/destinatario/documento` |\n| Nome, CEP, Número | Só para CPF: `/destinatario/nome`, `/destinatario/endereco/cep` e `/numero`. |\n| Código do produto | `/itens/*/produto` |\n| Quantidade, Valor unitário | `/itens/*/quantidade`, `/itens/*/valor_unitario` |\n| Forma de pagamento | `/pagamentos/0/forma`. Em branco: Pix (`pix_estatico`). |\n\nA Completa acrescenta operação, desconto, frete, quem paga o frete, e-mail do\ndestinatário e informações adicionais. Tudo o mais vem de regra, e aparece em\n`ajustes`: operação `venda` (`venda_consumidor_final` para CPF), presença\n`outros`, a série da planilha, modo `calcular`, sem frete.\n\nItem fora da cobertura do motor fica com erro e o motivo do motor; a nota nunca\nsai com valor estimado.\n\n### 3. O lote de NF-e\n\n`POST /v1/lotes` com `\"tipo\": \"nfe\"`: JSON (`itens` = corpos de\n`POST /v1/nfe`) ou multipart com `planilha`. Mesmos estados, mesmo\n`ao_validar` e o mesmo webhook `LOTE_EMISSAO_CONCLUIDO` do lote de NFS-e. O\nlimite (5.000, ou 100 com a chave de teste) conta os **itens das notas**, não as\nnotas. `GET /v1/lotes/{id}/itens` traz uma entrada por NF-e, com as `linhas`\nda planilha e o erro de cada uma (`linha`, `coluna`, `campo`).\n\n### 4. O destinatário recebe o XML e o DANFE\n\nCom e-mail do destinatário, a Sudrel manda o XML e o DANFE na autorização, e o XML\ndo cancelamento e da carta de correção. Homologação não manda e-mail.\n"
    },
    {
      "name": "Contingência da NF-e",
      "x-resumo": "Quando a SEFAZ de uma UF cai: esperar, SVC ou EPEC, sem nunca criar nota duplicada.",
      "description": "Quando a SEFAZ da UF da empresa cai, a nota pode esperar ou sair em\ncontingência. **A regra que vale sempre:** só vai para a contingência a nota\nque com certeza nunca chegou à SEFAZ. A nota que foi enviada e ficou sem\nresposta, ou que já ficou em `aguardando_confirmacao` alguma vez, fica em\n`aguardando_confirmacao` e se resolve pela consulta da chave quando a UF\nvoltar, em qualquer política. É o que impede duas NF-e para a mesma venda.\n\n### Política da empresa\n\n`politica_contingencia` no perfil fiscal (`PUT /v1/nfe/perfil-fiscal/{empresa_id}`):\n\n| Política | Nota que nunca saiu | Nota enviada sem resposta |\n|---|---|---|\n| `esperar` (padrão) | Fica `transmitindo` (`falha_envio.motivo: uf_indisponivel`) e sai quando a UF voltar | Fica `aguardando_confirmacao` |\n| `svc` | Vai para a SEFAZ Virtual de Contingência da UF, se a UF a ativou | Fica `aguardando_confirmacao` |\n| `epec` | Registra o EPEC no Ambiente Nacional e transmite à UF quando ela voltar | Fica `aguardando_confirmacao` |\n\nA política `svc` sem a SVC ativada pela SEFAZ da UF não emite: a nota espera,\ncom o motivo. PR e PB não aceitam EPEC: a nota espera.\n\n### SVC (SEFAZ Virtual de Contingência)\n\nA nota sai com `tpEmis` 6 (SVC-AN) ou 7 (SVC-RS, a da Bahia), com a data da\nentrada em contingência e o motivo no XML e no DANFE. A chave muda com o\n`tpEmis`; o número é o mesmo, porque a chave original nunca saiu (ela fica em\n`contingencia.chave_original` e em `chaves_anteriores`). Autorizada na SVC, a\nnota não volta à UF: a SVC a compartilha. Cancelamento vai à própria SVC;\ncarta de correção vai à UF (a SVC não tem CC-e).\n\n### EPEC\n\nA nota sai com `tpEmis` 4 e o evento EPEC (resumo da nota) é registrado no\nAmbiente Nacional. Com ele, o DANFE já vale: `GET /v1/nfe/{id}/danfe` traz o\nprotocolo do EPEC, o motivo e a hora da contingência. A NF-e vai à UF assim que\nela voltar, com a mesma chave e os mesmos dados. O prazo é de 168 horas do\nEPEC; faltando 24, o webhook `NFE_CONTINGENCIA` avisa. Se a UF rejeitar a NF-e,\na correção não pode mudar destinatário, data de emissão, total, ICMS nem\nICMS-ST (são os dados do EPEC): `contingencia.epec.correcao` explica.\n\n### Reconciliação\n\nQuando a UF volta, a Sudrel consulta a chave original de toda nota que foi\npara a contingência. Se ela existir na SEFAZ (o que não deveria acontecer), a\noriginal é cancelada dentro das 24 horas, você recebe `NFE_CONTINGENCIA` com\n`contingencia.situacao: duplicata_cancelada` e a equipe da Sudrel trata o caso\ncomo incidente.\n\n### Estado das UF\n\n`GET /v1/sefaz/status` mostra cada UF em que houve emissão recente no ambiente\nda sua chave: `normal`, `instavel` (um sinal ruim, a emissão não muda) ou\n`indisponivel`, a partir do status do serviço da SEFAZ e da taxa real de falha\ndas transmissões, e se a SVC está ativada. Mudou: webhook `SEFAZ_STATUS_ALTERADO`.\n\nFontes: NT 2013.007 v1.03 (SVC) e NT 2014.001 v1.41 (EPEC), do Portal Nacional da NF-e.\n"
    },
    {
      "name": "Emissão de NFC-e",
      "x-resumo": "NFC-e (modelo 65) pela API: caixas, cálculo pela Sudrel, QR Code, cupom de 80 mm e cancelamento em 30 minutos.",
      "description": "A NFC-e é a nota do varejo: venda presencial a consumidor final, dentro da UF.\nNa Sudrel ela é outro modelo da mesma emissão da NF-e: mesmo certificado,\nmesmo leiaute 4.00, mesmas garantias (o número é reservado na mesma transação\nque cria a nota, a chave nunca muda, e uma nota que pode ter chegado à SEFAZ só\nse resolve consultando a chave). A sandbox (`sdr_test_`) emite de verdade na\nhomologação da SEFAZ, sem valor fiscal; a chave `sdr_live_` emite na produção.\n\n### Antes da primeira NFC-e\n\n1. **Caixa.** Toda NFC-e sai de um caixa, e cada caixa tem a sua série (0 a 889,\n   única na empresa). Cadastre em `POST /v1/caixas` com o identificador que o\n   seu sistema usa (`LOJA1-CX02`). O sandbox tem os caixas dele.\n2. **Produtos e perfil fiscal.** No modo `calcular` (o padrão da NFC-e) a Sudrel\n   calcula os tributos pelo produto cadastrado; veja **Produtos e motor fiscal**.\n3. **CSC (opcional).** O QR Code sai na versão 3, que não usa o Código de\n   Segurança do Contribuinte. Se a SEFAZ da UF recusar a versão 3 (rejeição 407),\n   a Sudrel refaz a nota na versão 2, que precisa do CSC: cadastre-o em\n   `PUT /v1/nfce/csc/{empresa_id}` (`id_csc` e `csc`, como a SEFAZ entregou). O CSC\n   é guardado criptografado e nunca volta em resposta nem em log.\n4. **Prontidão.** `GET /v1/nfce/prontidao/{empresa_id}` diz o que falta, item por\n   item. A lista de itens cresce com as próximas fases.\n\n### A venda\n\n```http\nPOST /v1/nfce\nIdempotency-Key: CUPOM-000123\nPrefer: wait=15\n\n{\n  \"empresa_id\": \"0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00\",\n  \"referencia\": \"CUPOM-000123\",\n  \"caixa\": \"LOJA1-CX02\",\n  \"itens\": [{ \"produto\": \"CAM-1\", \"quantidade\": 2, \"valor_unitario\": 39.90 }],\n  \"pagamentos\": [{ \"forma\": \"dinheiro\", \"valor\": 100 }]\n}\n```\n\nA resposta vem na mesma chamada: **201** com a NFC-e autorizada, o `qr_code`, a\n`url_consulta`, o `troco` (o que os pagamentos passam do total, calculado) e os\nlinks do cupom. A `Idempotency-Key` é **obrigatória**: o caixa repete o pedido\nquando a rede cai, e a Sudrel devolve a mesma nota em vez de emitir outra.\n\n- `modo`: `calcular` (padrão), `informado` (os tributos de cada item vêm prontos,\n  como na NF-e) ou `conferir`.\n- `consumidor`: `{ \"documento\", \"nome\", \"email\" }`, opcional. Na BA é obrigatório a\n  partir de R$ 500,00 (RICMS/BA, art. 107-D, § 2º): sem ele, a venda volta 422\n  `nfce_consumidor_obrigatorio` antes de qualquer número.\n- Cartão e Pix levam o grupo do cartão: sem `cartao`, sai como POS sem integração;\n  com `\"cartao\": { \"integrado\": true, \"cnpj_credenciadora\", \"autorizacao\" }`, o TEF.\n\nA Sudrel confere as regras do modelo 65 antes de enviar e responde com o campo\ne a regra: CFOP (5101, 5102, 5103, 5104, 5115, 5405, 5656, 5667), CST do ICMS\n(00, 20, 40, 41, 60) e CSOSN (102, 103, 300, 400, 500) com o CFOP que combina,\nsem IPI, sem frete e só venda presencial.\n\n### Cupom\n\n`GET /v1/nfce/{id}/danfe` devolve o DANFE NFC-e de 80 mm em PDF, no leiaute do\nManual de Padrões DANFE NFC-e e QR Code (v6.0), com o QR Code e a mensagem de\nhomologação quando for o caso. Com `?formato=texto`, o mesmo cupom em 48 colunas\npara impressora térmica (o QR Code vai como o texto do `qr_code`, que a impressora\ndesenha). `POST /v1/nfce/{id}/envio` manda o cupom e o XML por e-mail ao consumidor.\n\n### Cancelamento\n\n`POST /v1/nfce/{id}/cancelamento`, com `justificativa` de 15 a 255 caracteres, até\n`cancelavel_ate`: 30 minutos depois da autorização na BA (RICMS/BA, art. 107-H, I).\nFora do prazo a resposta é 422 `cancelamento_fora_do_prazo`, com o caminho que a\nlegislação da UF dá; na BA não existe cancelamento extemporâneo de NFC-e. O\ncancelamento tem fila própria, separada da emissão: um pico de vendas não segura\num cancelamento.\n\n### Estados e eventos\n\nOs mesmos estados da NF-e (`autorizada`, `rejeitada`, `denegada`, `cancelada`,\n`descartada`, `transmitindo`, `aguardando_confirmacao`). Webhooks: `NFCE_AUTORIZADA`,\n`NFCE_REJEITADA`, `NFCE_DENEGADA`, `NFCE_CANCELADA`, `NFCE_DESCARTADA`,\n`NFCE_DESCARTE_PROXIMO` e `NFCE_ENVIO_PAUSADO`, com a NFC-e inteira em `dados`. As\nlistas de estados e de eventos crescem: trate valor desconhecido sem quebrar.\n\nNFC-e e NF-e são separadas na API: `GET /v1/nfe` não lista NFC-e, e\n`GET /v1/nfce/{id}` não encontra NF-e, mesmo com o id certo. A `referencia` e a\n`Idempotency-Key` são únicas por modelo.\n\nFontes: MOC 7.0 (Anexo I, regras do modelo 65), Manual de Padrões DANFE NFC-e e QR\nCode v6.0, NT 2025.001 v1.03 (QR Code versão 3), RICMS/BA (Decreto 13.780/2012).\n"
    },
    {
      "name": "Início rápido de NF-e",
      "x-resumo": "A primeira NF-e no sandbox: a Sudrel calcula os tributos e completa o destinatário pelo CNPJ.",
      "description": "Tudo com a chave de teste (`sdr_test_`): a nota vai de verdade à homologação\nda SEFAZ, sem valor fiscal e sem cobrança, e o cadastro de produtos do sandbox\né separado do de produção. Nos exemplos, a chave está em `SUDREL_API_KEY` e o\nid da empresa (de `GET /v1/companies`) em `EMPRESA`. Prefere clicar a copiar\ncurl? A mesma sequência está na\n[coleção do Postman](#tag/openapi-e-postman).\n\n**1. Prontidão.** Certificado A1 do CNPJ, inscrição estadual ativa na SEFAZ,\nendereço completo e regime tributário:\n\n```bash\ncurl https://api.sudrel.com.br/api/v1/nfe/prontidao/$EMPRESA \\\n  -H \"Authorization: Bearer $SUDREL_API_KEY\"\n```\n\n**2. Produto.** Cadastre uma vez; NCM, CEST e GTIN são conferidos nas tabelas\noficiais aqui, não na nota:\n\n```bash\ncurl https://api.sudrel.com.br/api/v1/produtos \\\n  -H \"Authorization: Bearer $SUDREL_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"empresa_id\":\"'$EMPRESA'\",\"codigo\":\"SKU-123\",\"descricao\":\"Camiseta de algodão\",\"ncm\":\"61091000\",\"unidade\":\"UN\",\"origem\":\"0\",\"perfil_fiscal\":{\"icms\":\"tributado\",\"pis_cofins\":\"tributado\",\"ibs_cbs\":{\"cst\":\"000\",\"classificacao_tributaria\":\"000001\"}}}'\n```\n\n**3. Perfil da empresa e aprovação.** Grave o perfil fiscal da empresa e\naprove os dois perfis: nada é calculado sem uma pessoa aprovar. No sandbox,\naprove você mesmo:\n\n```bash\ncurl -X PUT https://api.sudrel.com.br/api/v1/nfe/perfil-fiscal/$EMPRESA \\\n  -H \"Authorization: Bearer $SUDREL_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"contribuinte_ipi\":false}'\n\ncurl https://api.sudrel.com.br/api/v1/nfe/perfil-fiscal/$EMPRESA/aprovacao \\\n  -H \"Authorization: Bearer $SUDREL_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"aprovado_por\":{\"nome\":\"Ana Souza\",\"email\":\"ana@escritorio.com.br\"}}'\n\ncurl \"https://api.sudrel.com.br/api/v1/produtos/SKU-123/aprovacao-perfil?empresa_id=$EMPRESA\" \\\n  -H \"Authorization: Bearer $SUDREL_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"aprovado_por\":{\"nome\":\"Ana Souza\",\"email\":\"ana@escritorio.com.br\"}}'\n```\n\nEsse perfil serve ao Simples Nacional. Empresa do regime normal acrescenta\n`\"regime_pis_cofins\"` (`cumulativo` ou `nao_cumulativo`); veja **Produtos e\nmotor fiscal**.\n\n**4. Emita.** Só o CNPJ do destinatário, o produto, a quantidade e o valor:\n\n```bash\ncurl https://api.sudrel.com.br/api/v1/nfe \\\n  -H \"Authorization: Bearer $SUDREL_API_KEY\" \\\n  -H \"Idempotency-Key: 8f1c2e4a-1b2c-4d5e-9f00-112233445566\" \\\n  -H \"Prefer: wait=15\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"empresa_id\": \"'$EMPRESA'\",\n    \"referencia\": \"PED-10294\",\n    \"modo\": \"calcular\",\n    \"presenca\": \"internet\",\n    \"destinatario\": { \"documento\": \"13937073000156\" },\n    \"itens\": [ { \"produto\": \"SKU-123\", \"quantidade\": 2, \"valor_unitario\": 89.90 } ],\n    \"pagamentos\": [ { \"forma\": \"pix\" } ]\n  }'\n```\n\nA Sudrel busca nome e endereço do CNPJ na Receita e a inscrição estadual na\nSEFAZ, resolve CFOP, natureza da operação e tributos, e põe no pagamento o\nvalor da nota calculada. Cada valor volta em `ajustes`, com a regra e a fonte\nlegal. O CNPJ precisa existir na Receita: o do exemplo é o da SEFAZ-BA; troque\npelo de um cliente seu. CNPJ inventado volta `destinatario_nao_encontrado`.\n\n| Resposta | O que aconteceu | Próximo passo |\n|---|---|---|\n| 201 `autorizada` | Protocolo e chave de acesso preenchidos. | Baixe o DANFE em `GET /v1/nfe/PED-10294/danfe`. |\n| 202 `transmitindo` | A Sudrel continua cuidando. | Espere o webhook `NFE_AUTORIZADA` ou consulte `GET /v1/nfe/PED-10294`. **Não emita de novo.** |\n| 422 `fora_de_cobertura` | O motor não calcula esta operação (lista em `fora_de_cobertura`). | Mande a mesma nota no modo informado, com os tributos. |\n| 422 `nfe_rejeitada` | A SEFAZ recusou. | Leia `rejeicao` e corrija em `POST /v1/nfe/{id}/correcao`. |\n\n**Validar antes é opcional.** `POST /v1/nfe/previas` recebe o mesmo corpo e\ndevolve `erros`, `ajustes` e o XML que seria enviado, sem reservar número. A\nemissão faz as mesmas conferências, então a prévia serve para ver o XML antes\nou validar no seu sistema, não é um passo obrigatório.\n\n**O seu ERP já calcula os tributos?** Pule os passos 2 e 3 e mande, em cada\nitem, `codigo`, `descricao`, `ncm`, `cfop`, `origem`, `unidade` e os grupos\n`icms`, `pis` e `cofins` (modo `informado`, o padrão). O exemplo **venda** de\n`POST /v1/nfe` tem o corpo completo, e\n[Emissão de NF-e](#tag/emissão-de-nf-e) tem a tabela do que é obrigatório em\ncada modo.\n\nPara testar os desvios sem depender da SEFAZ, use o cabeçalho\n`X-Sudrel-Simular` (veja [Simulador de falhas](#tag/simulador-de-falhas)).\n"
    },
    {
      "name": "Webhooks",
      "x-resumo": "Avisos assinados com HMAC, retentativa por 72 horas, reenvio, troca de segredo e verificação em 4 linguagens.",
      "description": "### Implementação mínima\n\nToda entrega é um `POST` no seu endereço, com corpo `{ \"tipo\", \"dados\" }`:\n\n```http\nPOST /webhooks/sudrel HTTP/1.1\nContent-Type: application/json\nX-Sudrel-Event: NFSE_AUTORIZADA\nX-Sudrel-Event-Id: 6f1d2c3b-4a59-4e8f-9c0d-1a2b3c4d5e6f\nX-Sudrel-Delivery-Id: 0a9b8c7d-6e5f-4a3b-2c1d-0e9f8a7b6c5d\nX-Sudrel-Timestamp: 1791043200\nX-Sudrel-Signature-V2: t=1791043200,v1=<HMAC-SHA256 em hex>\nX-Sudrel-Signature: <HMAC-SHA256 em hex>\n\n{\"tipo\":\"NFSE_AUTORIZADA\",\"dados\":{\"id\":\"9d2f0c1e-3a4b-4c5d-8e9f-0a1b2c3d4e5f\",\"referencia\":\"PED-1001\",\"status\":\"autorizada\", \"...\": \"a nota inteira\"}}\n```\n\nO seu recebedor faz, nesta ordem: confere a assinatura e o horário, ignora o\n`X-Sudrel-Event-Id` já processado, guarda o evento numa fila sua e responde\n2xx. O processamento vem depois, fora da requisição.\n\nCadastre pelo painel (**Painel → Webhooks**) ou por `POST /v1/webhooks`. O\nsegredo do webhook só é exibido uma vez, na criação ou na troca: guarde com o\nmesmo cuidado de uma senha.\n\n### Cabeçalhos\n\n| Cabeçalho | Conteúdo |\n|---|---|\n| `X-Sudrel-Event` | O mesmo valor de `tipo` do corpo. |\n| `X-Sudrel-Event-Id` | Id do evento. O MESMO em todas as tentativas e reenvios: deduplique por ele. É o `id` de `GET /v1/eventos`. |\n| `X-Sudrel-Delivery-Id` | Id desta entrega (uma por evento e webhook; um reenvio é uma entrega nova). Aparece em `GET /v1/webhooks/{id}/entregas`. |\n| `X-Sudrel-Timestamp` | Momento desta tentativa, em segundos desde 1970 (UTC). |\n| `X-Sudrel-Signature-V2` | `t=<timestamp>,v1=<assinatura>`. A assinatura é o HMAC-SHA256 (hex) de `\"<timestamp>.<corpo bruto>\"` com o segredo do webhook. **Use esta.** |\n| `X-Sudrel-Signature` | HMAC-SHA256 (hex) só do corpo bruto. Mantida para quem já integrou; não protege contra reenvio de um corpo capturado. |\n\n### Eventos disponíveis\n\n| Evento | Quando sai |\n|---|---|\n| `NOTA_RECEBIDA`, `NFE_RECEBIDA`, `CTE_RECEBIDA` | Um documento novo foi capturado. |\n| `EVENTO_FISCAL_RECEBIDO` | Um evento (cancelamento, substituição etc.) foi capturado para um documento já conhecido. |\n| `NFSE_AUTORIZADA`, `NFSE_REJEITADA`, `NFSE_CANCELADA` | Uma NFS-e emitida pela sua conta mudou de situação. |\n| `NFSE_PROCESSAMENTO_PROLONGADO` | A nota está há 30 minutos transmitindo (aviso, sem mudança de status). Uma vez. |\n| `NFSE_AGUARDANDO_CONFIRMACAO` | A competência acabou antes da transmissão, e a nota espera você confirmar. |\n| `NFSE_FALHA_TRANSMISSAO` | A nota chegou a `falha_transmissao`, estado final. Veja `falha.dps_enviada` antes de emitir de novo. |\n| `NFE_AUTORIZADA`, `NFE_REJEITADA`, `NFE_DENEGADA`, `NFE_CANCELADA` | Uma NF-e emitida pela sua conta mudou de situação. |\n| `NFE_CARTA_CORRECAO_REGISTRADA` | Uma carta de correção foi registrada na SEFAZ. |\n| `NFE_DESCARTADA` | Uma NF-e rejeitada foi descartada (por você ou, perto do prazo de inutilização, pela Sudrel). |\n| `NFE_DESCARTE_PROXIMO` | Uma NF-e rejeitada sem correção vai ser descartada pela Sudrel em alguns dias. Uma vez. |\n| `NFE_ENVIO_PAUSADO` | A SEFAZ recusou o certificado da empresa várias vezes seguidas e a Sudrel parou de reenviar a NF-e. Ela volta sozinha quando o certificado passar no teste. |\n| `NFE_CONTINGENCIA` | Uma NF-e entrou em contingência (SVC ou EPEC), teve o EPEC registrado, foi rejeitada pela UF depois do EPEC, está a 24 horas do prazo do EPEC, ou a reconciliação encontrou e resolveu uma duplicata. O que aconteceu está em `contingencia.situacao`. |\n| `NFCE_AUTORIZADA`, `NFCE_REJEITADA`, `NFCE_DENEGADA`, `NFCE_CANCELADA`, `NFCE_DESCARTADA` | Uma NFC-e emitida pela sua conta mudou de situação. |\n| `NFCE_DESCARTE_PROXIMO`, `NFCE_ENVIO_PAUSADO` | Os mesmos avisos da NF-e, para a NFC-e. |\n| `SEFAZ_STATUS_ALTERADO` | O estado da SEFAZ de uma UF em que a sua conta emitiu nos últimos 7 dias mudou (`normal`, `instavel`, `indisponivel`), ou a SVC dela foi ativada ou desativada. |\n| `LOTE_EMISSAO_CONCLUIDO` | Um lote terminou (nenhuma nota dele está mais transmitindo). Uma vez por lote. |\n| `EMPRESA_PRONTIDAO_ALTERADA` | Um item da prontidão de uma empresa mudou de situação (por exemplo, o certificado entrou nos últimos 30 dias de validade). Conferido a cada 6 horas, só em produção. |\n\n### O que vem em `dados`\n\n| Eventos | `dados` |\n|---|---|\n| `NFSE_AUTORIZADA`, `NFSE_REJEITADA`, `NFSE_CANCELADA`, `NFSE_PROCESSAMENTO_PROLONGADO`, `NFSE_AGUARDANDO_CONFIRMACAO`, `NFSE_FALHA_TRANSMISSAO` | A nota inteira, igual a `GET /v1/nfse/{id}` |\n| `NFE_AUTORIZADA`, `NFE_REJEITADA`, `NFE_DENEGADA`, `NFE_CANCELADA`, `NFE_CARTA_CORRECAO_REGISTRADA`, `NFE_DESCARTADA`, `NFE_DESCARTE_PROXIMO`, `NFE_ENVIO_PAUSADO`, `NFE_CONTINGENCIA` | A NF-e inteira, igual a `GET /v1/nfe/{id}` |\n| `NFCE_AUTORIZADA`, `NFCE_REJEITADA`, `NFCE_DENEGADA`, `NFCE_CANCELADA`, `NFCE_DESCARTADA`, `NFCE_DESCARTE_PROXIMO`, `NFCE_ENVIO_PAUSADO` | A NFC-e inteira, igual a `GET /v1/nfce/{id}` |\n| `SEFAZ_STATUS_ALTERADO` | A UF, igual a um item de `GET /v1/sefaz/status`, mais `estado_anterior` |\n| `LOTE_EMISSAO_CONCLUIDO` | O lote, igual a `GET /v1/lotes/{id}` |\n| `EMPRESA_PRONTIDAO_ALTERADA` | A prontidão, igual a `GET /v1/companies/{id}/prontidao`, mais `alterados` (`[{ item, de, para }]`) |\n| `NOTA_RECEBIDA`, `NFE_RECEBIDA`, `CTE_RECEBIDA` | Um resumo: `{ notaId, empresaId, chaveAcesso, nsu }`. O documento completo está em `GET /v1/documents/{id}`, com o `notaId`. Na captura pela Prefeitura de São Paulo, vem `origem: \"PREFEITURA_SP\"` no lugar de `nsu`. |\n| `EVENTO_FISCAL_RECEBIDO` | `{ eventoId, notaId, empresaId, tipoEvento, nsu }`. O documento, com os eventos, está em `GET /v1/documents/{id}`, com o `notaId`. |\n| `webhook.teste` (só no teste manual) | `{ mensagem, testeId }` |\n\nOs eventos de documento recebido usam nomes em camelCase (`notaId`), como as\nrotas de documentos; os de emissão usam snake_case, como as rotas de emissão.\n\n### Como receber um webhook\n\n1. **Leia o corpo bruto** (os bytes exatos, antes de qualquer\n   `JSON.parse`) e confira o `X-Sudrel-Signature-V2` com o seu segredo.\n   Recuse se o `t=` estiver a mais de **5 minutos** do seu relógio: é\n   isso que impede alguém de reenviar um corpo capturado.\n2. **Responda 2xx rápido** (em até 10 segundos) e processe depois, numa\n   fila sua. Qualquer coisa diferente de 2xx, ou nenhuma resposta, conta\n   como falha e entra na retentativa.\n3. **Deduplique pelo `X-Sudrel-Event-Id`.** A mesma notícia pode chegar\n   mais de uma vez (retentativa depois de um 2xx que se perdeu, reenvio\n   pedido por você). Guarde os ids já processados.\n4. **Depois de uma queda do seu lado**, leia `GET /v1/eventos` a partir\n   do último cursor que você guardou. O log tem TODO evento da conta,\n   mesmo os que não tinham webhook assinando.\n\n### Verificando a assinatura\n\nDurante a troca de segredo o cabeçalho traz duas assinaturas\n(`t=...,v1=<nova>,v1=<antiga>`); basta uma bater. Os exemplos abaixo\nsão os mesmos arquivos que os nossos testes executam contra uma entrega\nde verdade.\n\nTypeScript (Node.js):\n\n```ts\nimport { createHmac, timingSafeEqual } from 'crypto';\n\n/** Tolerância recomendada: 5 minutos entre o `t=` e o seu relógio. */\nexport const TOLERANCIA_SEGUNDOS = 300;\n\n/**\n * Confere o `X-Sudrel-Signature-V2` de uma entrega da Sudrel.\n * `corpoBruto` é o corpo exatamente como chegou, antes de qualquer JSON.parse.\n * Durante a troca de segredo vêm dois `v1=`: basta um bater.\n */\nexport function webhookSudrelValido(\n  corpoBruto: string | Buffer,\n  cabecalhoV2: string | undefined,\n  segredo: string,\n  agoraSegundos: number = Math.floor(Date.now() / 1000),\n): boolean {\n  if (!cabecalhoV2) return false;\n  let timestamp = '';\n  const assinaturas: string[] = [];\n  for (const parte of cabecalhoV2.split(',')) {\n    const [chave, valor = ''] = parte.trim().split('=', 2);\n    if (chave === 't') timestamp = valor;\n    else if (chave === 'v1' && valor) assinaturas.push(valor);\n  }\n  if (!/^\\d+$/.test(timestamp)) return false;\n  if (Math.abs(agoraSegundos - Number(timestamp)) > TOLERANCIA_SEGUNDOS) return false;\n  const esperada = createHmac('sha256', segredo).update(`${timestamp}.`).update(corpoBruto).digest();\n  return assinaturas.some((assinatura) => {\n    const recebida = Buffer.from(assinatura, 'hex');\n    return recebida.length === esperada.length && timingSafeEqual(recebida, esperada);\n  });\n}\n```\n\nPHP:\n\n```php\n<?php\n// Tolerância recomendada: 5 minutos entre o t= e o seu relógio.\nconst TOLERANCIA_SEGUNDOS = 300;\n\n// $corpoBruto = file_get_contents('php://input');\n// $cabecalhoV2 = $_SERVER['HTTP_X_SUDREL_SIGNATURE_V2'] ?? null;\nfunction webhookSudrelValido(string $corpoBruto, ?string $cabecalhoV2, string $segredo, ?int $agora = null): bool\n{\n    if (!$cabecalhoV2) {\n        return false;\n    }\n    $timestamp = '';\n    $assinaturas = [];\n    foreach (explode(',', $cabecalhoV2) as $parte) {\n        [$chave, $valor] = array_pad(explode('=', trim($parte), 2), 2, '');\n        if ($chave === 't') {\n            $timestamp = $valor;\n        } elseif ($chave === 'v1' && $valor !== '') {\n            $assinaturas[] = $valor;\n        }\n    }\n    if (!ctype_digit($timestamp)) {\n        return false;\n    }\n    $agora = $agora ?? time();\n    if (abs($agora - (int) $timestamp) > TOLERANCIA_SEGUNDOS) {\n        return false;\n    }\n    $esperada = hash_hmac('sha256', $timestamp . '.' . $corpoBruto, $segredo);\n    foreach ($assinaturas as $assinatura) {\n        if (hash_equals($esperada, $assinatura)) {\n            return true;\n        }\n    }\n    return false;\n}\n```\n\nPython:\n\n```python\nimport hashlib\nimport hmac\nimport time\n\n# Tolerância recomendada: 5 minutos entre o t= e o seu relógio.\nTOLERANCIA_SEGUNDOS = 300\n\n\ndef webhook_sudrel_valido(corpo_bruto: bytes, cabecalho_v2: str, segredo: str, agora: int = None) -> bool:\n    \"\"\"Confere o X-Sudrel-Signature-V2. corpo_bruto: o corpo exatamente como chegou (bytes).\"\"\"\n    if not cabecalho_v2:\n        return False\n    timestamp, assinaturas = \"\", []\n    for parte in cabecalho_v2.split(\",\"):\n        chave, _, valor = parte.strip().partition(\"=\")\n        if chave == \"t\":\n            timestamp = valor\n        elif chave == \"v1\" and valor:\n            assinaturas.append(valor)\n    if not timestamp.isdigit():\n        return False\n    agora = int(time.time()) if agora is None else agora\n    if abs(agora - int(timestamp)) > TOLERANCIA_SEGUNDOS:\n        return False\n    esperada = hmac.new(segredo.encode(), timestamp.encode() + b\".\" + corpo_bruto, hashlib.sha256).hexdigest()\n    return any(hmac.compare_digest(esperada, assinatura) for assinatura in assinaturas)\n```\n\nC# (.NET 6 ou mais novo):\n\n```csharp\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Security.Cryptography;\nusing System.Text;\n\npublic static class WebhookSudrel\n{\n    // Tolerância recomendada: 5 minutos entre o t= e o seu relógio.\n    public const int ToleranciaSegundos = 300;\n\n    // corpoBruto: o corpo exatamente como chegou (leia o stream antes de desserializar).\n    public static bool Valido(byte[] corpoBruto, string? cabecalhoV2, string segredo, long? agora = null)\n    {\n        if (string.IsNullOrEmpty(cabecalhoV2)) return false;\n        var timestamp = \"\";\n        var assinaturas = new List<string>();\n        foreach (var parte in cabecalhoV2.Split(','))\n        {\n            var chaveValor = parte.Trim().Split('=', 2);\n            if (chaveValor.Length != 2) continue;\n            if (chaveValor[0] == \"t\") timestamp = chaveValor[1];\n            else if (chaveValor[0] == \"v1\" && chaveValor[1].Length > 0) assinaturas.Add(chaveValor[1]);\n        }\n        if (!long.TryParse(timestamp, NumberStyles.None, CultureInfo.InvariantCulture, out var t)) return false;\n        var momento = agora ?? DateTimeOffset.UtcNow.ToUnixTimeSeconds();\n        if (Math.Abs(momento - t) > ToleranciaSegundos) return false;\n\n        var prefixo = Encoding.UTF8.GetBytes(timestamp + \".\");\n        var dados = new byte[prefixo.Length + corpoBruto.Length];\n        prefixo.CopyTo(dados, 0);\n        corpoBruto.CopyTo(dados, prefixo.Length);\n        using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(segredo));\n        var esperada = hmac.ComputeHash(dados);\n        foreach (var assinatura in assinaturas)\n        {\n            byte[] recebida;\n            try { recebida = Convert.FromHexString(assinatura); }\n            catch (FormatException) { continue; }\n            if (CryptographicOperations.FixedTimeEquals(recebida, esperada)) return true;\n        }\n        return false;\n    }\n}\n```\n\n### Retentativas\n\nA primeira tentativa é na hora. Se falhar, tentamos de novo com estes\nintervalos, contados da tentativa anterior:\n\n| Tentativa | Espera | Desde a primeira |\n|---|---|---|\n| 2 | 1 min | 1 min |\n| 3 | 5 min | 6 min |\n| 4 | 15 min | 21 min |\n| 5 | 30 min | 51 min |\n| 6 | 1 h | 1 h 51 |\n| 7 | 2 h | 3 h 51 |\n| 8 | 4 h | 7 h 51 |\n| 9 | 8 h | 15 h 51 |\n| 10 a 13 | 12 h cada | até 63 h 51 |\n| 14 | o que faltar | 72 h |\n\nDepois de **72 horas** a entrega fica `falhou` e para. Ela continua\nlistada em `GET /v1/webhooks/{id}/entregas?status=falhou` e pode ser\nreenviada. Se TODAS as entregas de um webhook falharem por mais de 72\nhoras, o titular da conta recebe um e-mail, uma vez por queda. O\nwebhook não é desligado.\n\n### Reenvio\n\n`POST /v1/webhooks/{id}/reenvio` com um evento (`evento_id`), um período\n(`desde` e `ate`) ou um lote (`lote_id`). Cada evento vira uma entrega\nnova, com o MESMO `X-Sudrel-Event-Id`. Se o evento aconteceu quando\nninguém assinava, o corpo é montado na hora do reenvio e mostra o\nrecurso como ele está AGORA (por exemplo, uma nota autorizada e depois\ncancelada chega com `status: \"cancelada\"` no reenvio do\n`NFSE_AUTORIZADA`). No máximo 500 eventos por chamada; a resposta diz o\ntotal e, se faltar, de onde continuar (`continuar_desde`).\n\n### Rotação do segredo\n\n`POST /v1/webhooks/{id}/rotacao-segredo` devolve o segredo novo. Por 24\nhoras as entregas levam as duas assinaturas no `X-Sudrel-Signature-V2`,\nentão dá tempo de trocar o segredo do seu lado sem perder nada. O\n`X-Sudrel-Signature` antigo já sai só com o segredo novo.\n\n### Endereço, tempo e redirecionamento\n\n- O endereço precisa ser `https://` ou `http://` público. Endereço de rede\n  interna ou reservado (`localhost`, `10.x`, `192.168.x`, `100.64.x`,\n  IPv6 privado ou de link-local, e afins) é recusado no cadastro e em cada\n  entrega. Num domínio, todos os IPs que ele resolve são conferidos: basta\n  um interno para recusar.\n- Sucesso é qualquer 2xx em até **10 segundos**. Redirecionamento (3xx) não é\n  seguido e conta como falha: cadastre o endereço final.\n- O segredo tem 48 caracteres. A chave do HMAC é o segredo como texto, do\n  jeito que veio.\n\n### Ambientes\n\nWebhook criado com chave `sdr_test_` é de sandbox: recebe só eventos de\nsandbox. O de produção (chave `sdr_live_` ou painel) recebe só os de\nprodução. Cada chave só enxerga os webhooks do seu ambiente.\n\n### Cabeçalhos seus\n\nAté 5 cabeçalhos por webhook (`cabecalhos: [{ \"nome\", \"valor\" }]`), por\nexemplo um `Authorization` do seu gateway. Guardados criptografados e\nnunca devolvidos (a API mostra só os nomes). `Content-Type`,\n`Content-Length`, `Host`, `Transfer-Encoding`, `Connection` e qualquer\n`X-Sudrel-*` são nossos e não podem ser trocados (422).\n"
    },
    {
      "name": "Eventos",
      "x-resumo": "O log de eventos da conta, por cursor, com 90 dias de retenção.",
      "description": "O log de eventos da conta: todo evento, com ou sem webhook, em ordem.\nLeia com `GET /v1/eventos?apos=<cursor>` e guarde o `proximo_cursor` de\ncada resposta (ele vem mesmo quando a página está vazia). Os eventos vêm em\nordem, e o cursor só avança; nunca use data para paginar.\n\nO cursor é um texto opaco: guarde e devolva exatamente como veio, sem\ninterpretar. O `seq` de cada evento é o mesmo tipo de cursor. Até 02/10/2026\nele era um número; um cursor numérico guardado antes disso continua aceito em\n`apos`.\n\nSem `apos`, a leitura começa no evento mais antigo ainda guardado. Filtre por\ntipo com `tipos` (separados por vírgula). Cada evento traz `id` (o mesmo\n`X-Sudrel-Event-Id` do webhook), `tipo`, `ocorrido_em`, `ambiente`,\n`empresa_id`, `recurso` (`tipo`, `id` e `url` para ler o estado atual) e\n`dados`.\n\n`dados` vem preenchido quando o corpo foi guardado (havia webhook\nassinando o tipo, e sempre nos documentos recebidos); senão é `null` e\n`recurso.url` diz onde ler o estado atual.\n\n**Retenção: 90 dias.** Cursor mais velho do que isso responde 410\n`cursor_vencido`, com `cursor_mais_antigo`: continue a partir dele e\nconfira pelas rotas de leitura o que pode ter mudado no intervalo.\n"
    },
    {
      "name": "Simulador de falhas",
      "x-resumo": "Provoque timeout, rejeição, Sefin fora e falha de transmissão com a chave de teste.",
      "description": "Só com a chave `sdr_test_`. Mande o cabeçalho `X-Sudrel-Simular` em\n`POST /v1/nfse` (ou o campo `simular` em cada item de `POST /v1/lotes`).\nA nota simulada passa pelos MESMOS estados, eventos, webhooks e linha do\ntempo de uma nota real, mas **nunca vai à Sefin**, nem ao ambiente de\ntestes: quem responde é a Sudrel. Ela não consome a numeração da\nempresa (a DPS sai na série `49998`), a chave de acesso começa com sete\nzeros, o PDF sai com a marca **SIMULAÇÃO** e o recurso traz `simulacao`\ncom o cenário. Com a chave de produção, o pedido de simulação é 422\n`simulacao_so_no_sandbox`.\n\nOs prazos reais andam acelerados nas notas simuladas: os 10 minutos até\na recuperação perguntar pela DPS viram 5 segundos, os 30 minutos do\naviso de processamento prolongado viram 20 segundos, e os 7 dias até\n`falha_transmissao` viram 1 minuto.\n\n| Cenário | O que você vê |\n|---|---|\n| `autorizada_lenta` | Com a espera padrão (10 s), `202` com `transmitindo`; autorizada em cerca de 15 s. Webhook `NFSE_AUTORIZADA`. |\n| `rejeicao:<codigo>` | `422` com a nota `rejeitada`, `rejeicao.codigo_oficial` igual ao código pedido e `rejeicao.explicacao` quando ele está no catálogo (ex.: `rejeicao:E0240`). Webhook `NFSE_REJEITADA`. |\n| `timeout_depois_autorizada` | `202` com `transmitindo`. A transmissão \"cai\", a recuperação consulta a DPS, acha a nota e ela fica `autorizada`, UMA só, sem reenviar. Linha do tempo: `envio` (erro técnico), `consulta_dps` (encontrada), `recuperada`. Webhook `NFSE_AUTORIZADA`. |\n| `sefin_fora` | `202` com `transmitindo`, e continua `transmitindo` enquanto a \"Sefin está fora\". A consulta da DPS diz que ela não chegou, a nota é reenviada e autorizada (`envio`, `consulta_dps`, `reenfileirada`, `envio`). A API não tem um status \"agendada\": a espera aparece como `transmitindo`. |\n| `processamento_prolongado` | `202`. Depois de cerca de 20 s a nota ganha `aviso: { codigo: \"processamento_prolongado\" }` e sai o webhook `NFSE_PROCESSAMENTO_PROLONGADO`, uma vez; ela segue `transmitindo` e depois é autorizada. |\n| `falha_transmissao_nao_enviada` | `422` com `falha_transmissao` e `falha.dps_enviada: \"nao\"`: a nota parou antes do envio. Webhook `NFSE_FALHA_TRANSMISSAO`. |\n| `falha_transmissao_desconhecido` | `202`. O aviso de processamento prolongado aos 20 s e, cerca de 1 minuto depois, `falha_transmissao` com `falha.dps_enviada: \"desconhecido\"`: o caso em que é preciso conferir no Emissor Nacional antes de emitir de novo. Webhook `NFSE_FALHA_TRANSMISSAO`. |\n| `aguardando_confirmacao` | `202` com `aguardando_confirmacao` e o webhook `NFSE_AGUARDANDO_CONFIRMACAO`. Confirmada em `POST /v1/nfse/{id}/confirmacao`, a nota é autorizada. |\n\n### NF-e\n\nEm `POST /v1/nfe`, com a chave `sdr_test_`. A nota simulada nunca vai à\nSEFAZ, nem à homologação: quem responde é a Sudrel, e `simulacao` traz o\ncenário. Ela usa um número da série de homologação da empresa, que não é\ninutilizado.\n\n| Cenário | O que você vê |\n|---|---|\n| `timeout_depois_autorizada` | `202` com `transmitindo` ou `aguardando_confirmacao`. A resposta da SEFAZ \"se perde\", a Sudrel consulta a chave e a nota fica `autorizada`, UMA só, sem reenviar. Webhook `NFE_AUTORIZADA`. |\n| `denegada` | `422` `nfe_denegada` com `codigo_oficial` `302`. Webhook `NFE_DENEGADA`. |\n| `rejeicao:<cStat>` | `422` `nfe_rejeitada` com o `cStat` pedido (sem código, `225`) e a explicação quando ele está no catálogo (ex.: `rejeicao:778`). Webhook `NFE_REJEITADA`. |\n| `sefaz_indisponivel` | A primeira tentativa falha antes de sair; a seguinte autoriza. `202` e depois `autorizada`. |\n| `duplicidade_204` | A SEFAZ responde duplicidade (204); a consulta da chave acha a nota autorizada. Uma nota só. |\n| `uf_indisponivel` | A SEFAZ da UF fica fora por 2 minutos, sem SVC ativa. A nota segue a política de contingência da empresa: com `esperar` (padrão) fica `transmitindo` com `falha_envio.motivo: uf_indisponivel` e sai quando a UF volta. |\n| `uf_indisponivel_svc_ativo` | A UF fica fora por 2 minutos com a SVC ativada. Com a política `svc`, a nota sai autorizada na SVC (`contingencia.modo: svc_rs` ou `svc_an`, chave com tpEmis 6 ou 7). |\n| `epec_pendente` | Força o EPEC e a UF não volta: a nota fica `contingencia_epec`, com o protocolo e o prazo do EPEC e o DANFE de contingência. |\n| `epec_rejeitado` | Força o EPEC; a UF volta depois de 2 minutos e rejeita a NF-e (467, dados divergentes do EPEC). `contingencia.situacao: epec_rejeitado` diz como corrigir. |\n"
    },
    {
      "name": "Receitas",
      "x-resumo": "Fluxos completos: emitir uma nota, emitir milhares, sincronizar documentos, receber webhooks e retentar.",
      "description": "Fluxos completos para as tarefas mais comuns.\n\n### Emitir uma NFS-e\n\n```text\n1. GET  /v1/companies/{id}/prontidao        -> sem bloqueio? siga\n2. POST /v1/nfse/validacoes                 -> valida: true? siga\n3. POST /v1/nfse  (Idempotency-Key + referencia)\n4. 201 -> pronto | 202 -> passo 5 | 422 -> corrigir\n5. webhook NFSE_AUTORIZADA / NFSE_REJEITADA, ou GET /v1/nfse/{referencia}\n6. GET  /v1/nfse/{id}/pdf e /xml\n```\n\nO passo a passo com exemplos está em [Sua primeira nota](#tag/comece-aqui).\n\n### Emitir milhares de NFS-e\n\n```text\n1. POST /v1/lotes  { empresa_id, ao_validar, itens: [ { referencia, ... } ] }   -> 202\n2. webhook LOTE_EMISSAO_CONCLUIDO, ou GET /v1/lotes/{id} até status \"concluido\"\n3. GET  /v1/lotes/{id}/itens?status=rejeitada   (e com_erro_validacao)\n4. POST /v1/lotes/{id}/reprocessamento   { itens: [ { linha, campos } ] }\n5. GET  /v1/lotes/{id}/relatorio         -> a planilha com o resultado de cada linha\n```\n\nEscolha `ao_validar`: `emitir_validas` (padrão) emite as linhas boas e deixa as\nruins para corrigir; `aguardar` para depois da validação e só emite quando você\nchamar `POST /v1/lotes/{id}/emissao`, para quem quer tudo ou nada. Mande\n`referencia` em todo item. Detalhes em [Emissão em lote](#tag/emissão-em-lote).\n\n### Sincronizar documentos recebidos\n\n```text\nCarga inicial:\n1. GET /v1/documents?limite=100, seguindo proximoCursor até vir nulo\n2. para o detalhe e o XML: GET /v1/documents/{id}\n\nDaqui em diante:\n3. GET /v1/eventos?tipos=NOTA_RECEBIDA,NFE_RECEBIDA,CTE_RECEBIDA,EVENTO_FISCAL_RECEBIDO\n4. para cada evento: GET /v1/documents/{recurso.id}, e grave pelo id (atualiza se já existe)\n5. guarde o proximo_cursor e, na próxima rodada, leia com ?apos=<cursor>\n6. opcional: webhook com os mesmos tipos, para saber na hora; o log cobre o que o webhook perder\n```\n\nGrave pelo `id` do documento, atualizando se ele já existe: assim tanto faz\nreceber o mesmo documento pela carga inicial, pelo log e pelo webhook. Use uma\nchave `sdr_live_`: a chave de teste não lê documentos.\n\n### Receber webhooks sem perder nada\n\n```text\n1. POST /v1/webhooks  { url, eventos }        -> guarde o segredo\n2. a cada entrega: confira X-Sudrel-Signature-V2, responda 2xx em até 10 s\n3. deduplique por X-Sudrel-Event-Id\n4. depois de uma queda sua: GET /v1/eventos?apos=<último cursor guardado>\n```\n\nO código de verificação em quatro linguagens está em [Webhooks](#tag/webhooks).\n\n### Retentativa\n\n| Situação | Repetir? | Como |\n|---|---|---|\n| Timeout, conexão caiu, nenhuma resposta | Sim | Mesma `Idempotency-Key`, mesmo corpo. |\n| 500 `erro_interno`, 502, 503, 504 | Sim | Mesma `Idempotency-Key`, com espera crescente (1 s, 2 s, 4 s... até cerca de 1 minuto). |\n| 429 | Sim | Depois da virada do minuto. |\n| 409 `conflito` | Sim | Alguns segundos depois, mesma `Idempotency-Key`: a primeira chamada ainda estava em andamento. |\n| 409 `nfse_sem_pdf` | Sim | Mais tarde: o PDF ainda não existe. |\n| 202 `transmitindo` | **Não** repita a emissão | Acompanhe por webhook ou `GET /v1/nfse/{id}`. |\n| 409 `referencia_duplicada` | Não | A nota já existe: consulte pelo `nfse_id` que veio no erro. |\n| 409 `idempotencia_conflito` | Não | O seu sistema usou a mesma chave para corpos diferentes: corrija isso. |\n| 422 `nfse_rejeitada` | Não | Corrija e emita uma nota nova, com outra `referencia`. |\n| 422 `validacao`, 412, 400, 401, 403, 404 | Não | Corrija antes. Repetir dá o mesmo erro. |\n| `falha_transmissao` com `dps_enviada: \"nao\"` | Sim, como nota nova | A nota não chegou ao Sistema Nacional. Emita de novo com outra `referencia` (a nota em falha continua registrada), ou, se veio de lote, use `POST /v1/lotes/{id}/reprocessamento`. |\n| `falha_transmissao` com `dps_enviada: \"desconhecido\"` | Não, antes de conferir | A DPS pode ter virado nota. Confira no Emissor Nacional antes de emitir de novo. |\n\nA regra curta: repita o que vem com `retentavel: true` e os erros de rede,\nsempre com a MESMA `Idempotency-Key`. O resto, corrija antes.\n"
    },
    {
      "name": "Problemas comuns",
      "x-resumo": "O que fazer ao receber 401, 403, 404, 409, 412, 422, 429, webhook que não chega e nota parada.",
      "description": "Cada problema termina com o próximo passo. Se nenhum resolver, mande ao\nsuporte o `X-Request-Id` da chamada.\n\n### Recebi 401\n\nA chave não chegou ou não vale. Confira:\n\n- o cabeçalho é `Authorization: Bearer sdr_...`, com o espaço depois de `Bearer`;\n- a chave não foi revogada (painel, **Integrações › Chaves de API**);\n- o endereço tem o `/api`: `https://api.sudrel.com.br/api/v1/...`.\n\n### Recebi 403\n\nA chave não pode fazer isto. Duas causas:\n\n- **Chave de teste** (`sdr_test_`) em operação só de produção: criar ou\n  alterar empresa, enviar certificado, ler documentos recebidos. Use uma\n  `sdr_live_`.\n- **Chave restrita a uma empresa** acessando outra (`acesso_negado`) ou\n  administrando webhooks (`chave_restrita`). Use uma chave sem restrição.\n\n### Recebi 404 numa nota ou empresa que existe\n\nEla existe no outro ambiente. A chave de teste só enxerga notas de teste, e a\nde produção só as de produção. Confira o prefixo da chave.\n\n### Recebi 412\n\nA empresa não pode emitir: a prontidão tem um item em `bloqueio`. O corpo traz\na lista em `itens`, com `correcao` em cada um. Corrija e emita de novo. Veja\n[Prontidão](#tag/prontidão).\n\n### Recebi 202\n\nNão é erro. A nota está `transmitindo` e a Sudrel continua cuidando. Espere o\nwebhook ou consulte `GET /v1/nfse/{id}`. Não emita de novo.\n\n### Recebi 409\n\nLeia `codigo`:\n\n- `referencia_duplicada`: a nota já existe. Consulte pelo `nfse_id` do erro.\n- `idempotencia_conflito`: a mesma `Idempotency-Key` foi usada para outro\n  corpo. Gere uma chave por nota.\n- `conflito`: a mesma `Idempotency-Key` ainda está em andamento. Espere alguns\n  segundos e repita.\n- `referencia_ambigua`: a referência existe em duas empresas. Repita com\n  `?empresa_id=`.\n\nVeja [Idempotência](#tag/idempotência).\n\n### Recebi 422\n\nLeia `codigo`, e depois `erros` (cada um com `campo`, `mensagem` e\n`correcao`):\n\n- `validacao`: o JSON tem erro e nada foi criado. Corrija os itens de `erros`.\n- `nfse_rejeitada`: o Sistema Nacional recusou. Leia `codigo_oficial` e\n  `nfse.rejeicao.explicacao`, corrija e emita uma nota nova.\n- `tipo_invalido` em `/valor` ou numa alíquota: mande como texto, `\"1500.00\"`.\n\n### Recebi 429\n\nMais de 120 requisições no minuto nesta chave. Espere a virada do minuto e\nrepita. Se acontece sempre, troque consultas repetidas por webhook e notas\navulsas por lote.\n\n### O webhook não chegou\n\n1. Confira se o webhook assina o tipo de evento (`GET /v1/webhooks/{id}`) e se\n   está `ativo`.\n2. Confira o ambiente: webhook criado com a chave de teste só recebe eventos\n   de teste.\n3. Veja as tentativas em `GET /v1/webhooks/{id}/entregas`: status HTTP que o\n   seu servidor devolveu, ou `null` quando nem conectou.\n4. Seu servidor precisa responder **2xx em até 10 segundos**. Redirecionamento\n   (3xx) não é seguido e conta como falha. Endereço de rede interna é recusado.\n5. Mande um teste: `POST /v1/webhooks/{id}/teste`.\n6. Recupere o que perdeu: `POST /v1/webhooks/{id}/reenvio`, ou leia\n   `GET /v1/eventos`.\n\n### A assinatura do webhook não bate\n\n- Calcule o HMAC sobre o **corpo bruto**, os bytes exatos, antes de qualquer\n  `JSON.parse`. Reserializar o JSON muda os bytes.\n- A chave do HMAC é o segredo como texto, do jeito que veio na criação.\n- Use o `X-Sudrel-Signature-V2`: o HMAC é de `\"<t>.<corpo>\"`, não só do corpo.\n- Na troca de segredo vêm dois `v1=`: basta um bater.\n- Confira o relógio do servidor: a tolerância recomendada é de 5 minutos.\n\n### A nota parece travada\n\n1. `GET /v1/nfse/{id}`: veja `status` e a linha do tempo em `eventos`.\n2. `transmitindo` com `aviso.codigo = \"processamento_prolongado\"`: a Sudrel\n   ainda está cuidando. Não emita de novo.\n3. `aguardando_confirmacao`: está esperando você em\n   `POST /v1/nfse/{id}/confirmacao`.\n4. `falha_transmissao`: leia `falha.dps_enviada` antes de qualquer coisa.\n5. Veja a situação do serviço na [página de status](https://sudrel.com.br/status).\n\n### Não encontro uma chamada que fiz\n\nProcure pelo `X-Request-Id` (ou `requisicao_id`) em **Integrações › Log da\nAPI**, no painel. Ficam lá o pedido e a resposta, por 30 dias.\n"
    },
    {
      "name": "SDKs",
      "x-resumo": "SDKs de TypeScript e PHP e o que cada um cobre.",
      "description": "### SDKs oficiais\n\n| Linguagem | Pacote | Situação |\n|---|---|---|\n| Node.js / TypeScript | `@sudrel/sdk` (com a CLI `sudrel`) | [npm](https://www.npmjs.com/package/@sudrel/sdk): `npm install @sudrel/sdk` |\n| PHP 8.1+ | `sudrel/sdk` | [Packagist](https://packagist.org/packages/sudrel/sdk): `composer require sudrel/sdk` |\n\nA API é REST simples e não exige SDK. O guia\n[Sua primeira nota](#tag/comece-aqui) tem exemplos em `curl`, C# e Delphi,\ne [Webhooks](#tag/webhooks) tem a verificação da assinatura em TypeScript,\nPHP, Python e C#. Não há SDK de C#, Delphi, Python ou Ruby.\n\n### O que cada SDK cobre\n\n| Recurso | TypeScript | PHP | Sem SDK (REST) |\n|---|---|---|---|\n| Emitir, validar, consultar e listar NFS-e | Sim | Sim | Sim |\n| Esperar a nota sair de `transmitindo` | Sim (`nfse.esperar`) | Sim (`esperar`) | Consultando `GET /v1/nfse/{id}` |\n| Cancelar, confirmar, XML, PDF | Sim | Sim | Sim |\n| Substituir | Pelo bloco `substituicao` em `emitir` | Pelo bloco `substituicao` em `emitir` | Sim |\n| Lotes: criar (JSON ou planilha), consultar, itens, emitir, reprocessar | Sim | Sim | Sim |\n| Lotes: listar e relatório | Sim | Não | Sim |\n| Empresas: listar e prontidão | Sim | Sim | Sim |\n| Empresas: detalhar | Sim | Não | Sim |\n| Empresas: criar, certificado, pausar, retomar, remover | Não | Não | Sim |\n| Webhooks: criar, listar, alterar, remover, trocar segredo, testar, entregas, reenviar | Sim | Sim | Sim |\n| Webhooks: detalhar um | Sim | Não | Sim |\n| Verificar a assinatura do webhook | Sim | Sim | Exemplos em [Webhooks](#tag/webhooks) |\n| Log de eventos | Sim | Sim | Sim |\n| Documentos recebidos, conta, consumo, NBS, parâmetros do município | Não | Não | Sim |\n\nOs SDKs geram e reaproveitam a `Idempotency-Key` sozinhos, seguem a\npaginação por cursor e devolvem a nota também quando o Sistema Nacional\nrejeita (o 422 com `nfse`).\n\n### TypeScript\n\n```ts\nimport { Sudrel } from '@sudrel/sdk';\n\nconst sudrel = new Sudrel(); // lê SUDREL_API_KEY\nconst nota = await sudrel.nfse.emitir({\n  empresa_id: process.env.EMPRESA!,\n  referencia: 'PED-1001',\n  tomador: { documento: '11222333000181' },\n  valor: '1500.00',\n  servico: { descricao: 'Consultoria em sistemas' },\n});\nconsole.log((await sudrel.nfse.esperar(nota.id!)).status);\n```\n\nA CLI do mesmo pacote encaminha os eventos da conta para um recebedor local,\nassinados como uma entrega de verdade, sem expor porta e sem cadastrar\nwebhook:\n\n```bash\nnpx -p @sudrel/sdk sudrel eventos seguir --encaminhar http://localhost:3000/webhook\n```\n"
    },
    {
      "name": "OpenAPI e Postman",
      "x-resumo": "A especificação OpenAPI em JSON e YAML, e como importar no Postman ou no Insomnia.",
      "description": "### A especificação OpenAPI\n\nEsta documentação é gerada de uma especificação OpenAPI 3.0, e ela é a fonte\nde verdade das rotas, dos campos e dos erros:\n\n| Formato | Endereço |\n|---|---|\n| JSON | `https://sudrel.com.br/docs/openapi.json` |\n| YAML | `https://sudrel.com.br/docs/openapi.yaml` |\n| JSON em espanhol | `https://sudrel.com.br/docs/es/openapi.json` |\n| JSON em inglês | `https://sudrel.com.br/docs/en/openapi.json` |\n\nNas versões em espanhol e inglês só as explicações mudam: rotas, campos e\ncódigos são os mesmos.\n\nUse a especificação para gerar um cliente na sua linguagem (por exemplo com o\nOpenAPI Generator), para importar numa ferramenta de testes ou para dar\ncontexto a um assistente de IA.\n\n### Postman e Insomnia\n\n1. No Postman, **Import** e cole `https://sudrel.com.br/docs/openapi.json`.\n   No Insomnia, **Import** com o mesmo endereço.\n2. A coleção vem com todas as rotas e com o endereço base\n   `https://api.sudrel.com.br/api` numa variável da coleção. Para agrupar as\n   rotas pelas seções desta documentação, escolha organizar por tags na\n   importação.\n3. Na autenticação da coleção, escolha **Bearer Token** e cole a sua chave.\n   Comece com uma chave de teste (`sdr_test_`): com ela, a emissão vai ao\n   ambiente de testes do Sistema Nacional, sem valor fiscal.\n4. Guarde a chave numa variável de ambiente da ferramenta, nunca na coleção\n   que você compartilha.\n\n### Coleção pronta de NF-e\n\nPara a primeira NF-e, há uma coleção do Postman com a sequência do\n[Início rápido de NF-e](#tag/início-rápido-de-nf-e) na ordem, já com corpos\npreenchidos: prontidão, produto, perfil e aprovações, prévia (opcional),\nemissão no modo calcular e no informado, consulta, DANFE, XML e cancelamento.\n\n| Coleção | Endereço |\n|---|---|\n| NF-e, primeira nota | `https://sudrel.com.br/docs/postman/sudrel-nfe.postman_collection.json` |\n\nNo Postman, **Import** com o endereço. Depois preencha as variáveis da coleção:\n`chave_api` (a chave `sdr_test_`), `empresa_id` (de `GET /v1/companies`) e,\nse quiser, `destinatario_cnpj` (um CNPJ que exista na Receita; vem com o da\nSEFAZ-BA). A cada nota nova, troque `referencia` e `idempotency_key`; para\nrepetir a MESMA nota, mantenha os dois. Os corpos saem dos exemplos desta\ndocumentação, gerados a cada publicação, e por isso não ficam para trás.\n\n### Testar aqui mesmo\n\nNa [referência da API](/docs), cada rota tem o teste na própria página, na\ncoluna da direita: preencha a chave em **Auth** uma vez e ela vale para\ntodas as rotas, guardada no seu navegador. O teste chama a API de verdade:\ncom uma chave de produção, uma emissão vale como nota fiscal. Para testar\nemissão, use a chave de teste.\n"
    },
    {
      "name": "IA e MCP",
      "x-resumo": "Servidor MCP somente leitura para assistentes de IA, e orientações para quem escreve um agente.",
      "description": "### Servidor MCP: a Sudrel no seu assistente de IA\n\nO MCP (Model Context Protocol) é o padrão aberto que permite a um assistente\nde IA consultar sistemas externos. Com o servidor MCP da Sudrel, você pergunta\nem português e o assistente responde com os seus dados reais:\n\n- \"Quanto entrou de nota esse mês?\"\n- \"Algum fornecedor parou de faturar pra gente?\"\n- \"Me mostra as notas acima de R$ 5.000 de agosto\"\n- \"Quanto já usei da franquia do plano?\"\n\n**Situação:** o pacote [`@sudrel/mcp-server`](https://www.npmjs.com/package/@sudrel/mcp-server)\nestá publicado no npm. Ele roda no seu computador (transporte stdio), então funciona em\nclientes que executam servidor MCP local, como o Claude Desktop. Assistentes\nque só aceitam servidor remoto (ChatGPT, Claude na web) ainda não são\natendidos.\n\n### Instalação\n\nAdicione ao arquivo de configuração do seu cliente MCP.\nNo Claude Desktop, é o `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"sudrel\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@sudrel/mcp-server\"],\n      \"env\": { \"SUDREL_API_KEY\": \"sdr_live_...\" }\n    }\n  }\n}\n```\n\nUse uma chave de produção (`sdr_live_`): a chave de teste não lê documentos\nrecebidos. Código aberto, licença MIT. `SUDREL_API_URL` (opcional) muda o\nendereço da API; o padrão é `https://api.sudrel.com.br/api/v1`.\n\n### O que o agente pode e não pode fazer\n\n| Ferramenta | O que faz | Lê | Escreve |\n|---|---|---|---|\n| `consultar_conta` | Nome, status e ambiente da conta ligada à chave | Sim | Não |\n| `consultar_consumo` | Franquia usada no ciclo, saldo e excedente | Sim | Não |\n| `listar_empresas` | CNPJs da conta e o estado de cada um | Sim | Não |\n| `detalhar_empresa` | Detalhe de um CNPJ, incluindo certificado | Sim | Não |\n| `listar_documentos` | NFS-e, NF-e e CT-e capturadas, com filtro de período, fornecedor, valor, tipo e papel | Sim | Não |\n| `detalhar_documento` | Documento completo, com prestador, tomador, valores e tributos | Sim | Não |\n| `listar_notas_emitidas` | NFS-e emitidas pela conta (API, planilha ou painel), com filtro de situação | Sim | Não |\n| `detalhar_nota_emitida` | Nota emitida completa: linha do tempo, ajustes feitos pela Sudrel e, se rejeitada, a explicação com a correção | Sim | Não |\n| `listar_lotes` | Lotes de emissão, com as contagens por situação | Sim | Não |\n| `detalhar_lote` | Situação de um lote e quantas notas estão em cada situação | Sim | Não |\n| `listar_itens_lote` | Linhas de um lote e o resultado de cada uma | Sim | Não |\n| `consultar_prontidao_emissao` | Se a empresa pode emitir agora, item por item, com o que fazer em cada bloqueio | Sim | Não |\n| `listar_nfe_emitidas` | NF-e (modelo 55) emitidas pela conta, com filtro de situação | Sim | Não |\n| `detalhar_nfe_emitida` | NF-e completa: resposta da SEFAZ, cancelamento, cartas de correção e explicação da rejeição | Sim | Não |\n| `consultar_prontidao_nfe` | Se a empresa pode emitir NF-e agora, item por item | Sim | Não |\n| `listar_nfce_emitidas` | NFC-e (modelo 65) emitidas pela conta, com filtro de situação e de caixa | Sim | Não |\n| `detalhar_nfce_emitida` | NFC-e completa: caixa, QR Code, troco, consumidor e prazo de cancelamento | Sim | Não |\n| `consultar_prontidao_nfce` | Se a empresa pode emitir NFC-e agora, item por item | Sim | Não |\n| `listar_caixas_nfce` | Os caixas de NFC-e, com série e próximo número | Sim | Não |\n| `listar_inutilizacoes_nfe` | Faixas de números de NF-e inutilizadas pela Sudrel e por quê | Sim | Não |\n| `listar_produtos_nfe` | Produtos cadastrados para a NF-e, com o perfil fiscal e a aprovação | Sim | Não |\n| `detalhar_produto_nfe` | Um produto pelo código, com o perfil fiscal | Sim | Não |\n| `listar_eventos_recentes` | Log de eventos da conta (nota autorizada, rejeitada, cancelada, documento recebido...) | Sim | Não |\n\nValores em `listar_documentos` são filtrados em **centavos**: R$ 1.500,00\né `150000`. A própria descrição da ferramenta avisa isso ao modelo.\n\n**O agente não pode:** emitir, validar, cancelar ou substituir nota, criar ou\nalterar empresa, enviar certificado, criar webhook, nem qualquer outra\nescrita.\n\n### Somente leitura, e isso é uma decisão de projeto\n\nO servidor MCP da Sudrel **não emite nota, não cancela, não cria\nempresa e não remove nada**. Ele só lê. Os endpoints de escrita desta API\nexistem e funcionam, mas nenhum deles é exposto ao agente.\n\nO motivo é o modelo de ameaça do MCP. Um servidor MCP entrega as\nferramentas a um modelo que decide sozinho quando chamá-las, a partir de\ntexto que pode ter vindo de qualquer lugar, **inclusive do conteúdo de um\ndocumento fiscal que a própria ferramenta acabou de trazer**. A descrição\ndo serviço de uma nota é texto livre que qualquer fornecedor escreve. Num\nservidor que sabe emitir nota, esse texto passa a ser uma superfície de\ninjeção com consequência fiscal real.\n\nQuem precisa automatizar emissão usa a API REST direto, com código que\npassa por revisão e por um deploy, e não por um modelo decidindo no meio\nde uma conversa.\n\nInternamente, todo acesso do servidor MCP passa por uma única função que\nsó faz `GET`. Expor escrita exigiria mudar essa função de propósito, e\nisso é o atrito que se quer.\n\n### Para quem escreve um agente sobre a API REST\n\n- A especificação completa está em `https://sudrel.com.br/docs/openapi.json`\n  (e `/docs/openapi.yaml`). Um resumo em texto, pensado para modelos, está em\n  `https://sudrel.com.br/docs/llms.txt`.\n- Operações de leitura (todo `GET`) são seguras de repetir. As de escrita\n  (`POST`, `PATCH`, `DELETE`) têm efeito real; em `POST /v1/nfse` e\n  `POST /v1/lotes`, use sempre `Idempotency-Key` e `referencia`.\n- Faça o agente decidir por `codigo` e `status`, nunca por `mensagem`.\n- Teste com a chave `sdr_test_`: nada do que ela emite tem valor fiscal.\n- Siga as [Regras de integração](#tag/regras-de-integração).\n"
    },
    {
      "name": "Glossário",
      "x-resumo": "Os termos fiscais e técnicos usados nesta documentação.",
      "description": "| Termo | O que é |\n|---|---|\n| **NFS-e** | Nota Fiscal de Serviço eletrônica. A API emite e consulta. |\n| **NF-e** | Nota Fiscal eletrônica, de mercadoria (modelo 55). A API emite e consulta. |\n| **NFC-e** | Nota Fiscal de Consumidor eletrônica (modelo 65): a venda presencial a consumidor final, impressa como cupom com QR Code. A API emite. |\n| **CT-e** | Conhecimento de Transporte eletrônico. A API consulta; não emite. |\n| **Sistema Nacional NFS-e** | O sistema do governo federal que autoriza as NFS-e no padrão nacional. A Sudrel transmite para ele. |\n| **Produção restrita** | O ambiente de testes oficial do Sistema Nacional. É para onde vai a nota emitida com a chave `sdr_test_`. |\n| **Ambiente de Dados Nacional (ADN)** | De onde vêm as NFS-e recebidas e emitidas pelo CNPJ. |\n| **DPS** | Declaração de Prestação de Serviço: o documento que a Sudrel envia ao Sistema Nacional. Autorizada, ela vira a NFS-e. Tem série e número. |\n| **NSU** | Número Sequencial Único: a posição de um documento na distribuição do ambiente nacional. |\n| **Chave de acesso** | O identificador oficial de 50 dígitos de uma NFS-e autorizada (44 na NF-e e no CT-e). |\n| **Tomador** | Quem recebe o serviço (e paga). |\n| **Prestador** | Quem presta o serviço e emite a nota. Na emissão, é a sua empresa. |\n| **Competência** | O mês a que o serviço se refere, para fins de imposto (`AAAA-MM`). |\n| **Código de tributação nacional** | O código de 6 dígitos do serviço na lista nacional (ex.: `010701`). |\n| **NBS** | Nomenclatura Brasileira de Serviços. Exigida junto do IBS e da CBS. |\n| **ISS** | Imposto Sobre Serviços, municipal. |\n| **IBS e CBS** | Os tributos da reforma tributária sobre consumo. A DPS do regime regular já os declara. |\n| **Retenção** | Imposto que o tomador desconta do pagamento e recolhe no lugar do prestador. |\n| **Autorização** | O Sistema Nacional aceitou a DPS e gerou a NFS-e. |\n| **Rejeição** | O Sistema Nacional recusou a DPS, com um código `E` (ex.: `E0039`). |\n| **Transmissão** | O envio da DPS ao Sistema Nacional, com a recuperação de falhas técnicas. |\n| **Cancelamento** | Evento que anula uma NFS-e autorizada. |\n| **Substituição** | Emitir uma nota nova que cancela a anterior automaticamente, quando autorizada. |\n| **Prontidão** | A checagem do que a empresa precisa ter para emitir. Ver [Prontidão](#tag/prontidão). |\n| **Lote** | Muitas notas numa chamada, com resultado por linha. |\n| **Referência** | O identificador da nota no seu sistema (`referencia`). Única por empresa e ambiente. |\n| **Idempotência** | Repetir a mesma chamada sem criar nada a mais. Ver [Idempotência](#tag/idempotência). |\n| **Cursor** | O marcador que diz de onde continuar uma lista. Valor opaco. |\n| **Webhook** | Uma chamada HTTP que a Sudrel faz ao seu sistema quando algo acontece. |\n| **Evento** | Algo que aconteceu na conta (nota autorizada, documento recebido...). Fica no log de eventos por 90 dias. |\n| **Ajuste** | O que a Sudrel preencheu, omitiu ou derivou na nota por causa do município ou do cenário tributário. Vem em `ajustes`. |\n| **MCP** | Model Context Protocol: o padrão que permite a um assistente de IA consultar sistemas. Ver [IA e MCP](#tag/ia-e-mcp). |\n"
    },
    {
      "name": "Changelog",
      "x-resumo": "O que mudou na API e na documentação, por data.",
      "description": "API `v1`. Desde 02/10/2026 o contrato de emissão está congelado: só entram\nmudanças que **acrescentam** (campo, rota, evento, item de prontidão, código\nde erro). Nada que existe é renomeado, removido ou muda de status HTTP. Regra\nque precisa mudar de sentido ganha `id` novo.\n\n### 18/10/2026\n\n**Acrescentado (NFC-e, modelo 65)**\n- `POST /v1/nfce`, com resposta na mesma chamada e `Idempotency-Key` obrigatória;\n  prévia, consulta, lista, XML, descarte, envio por e-mail e inutilizações.\n- Caixas (`/v1/caixas`), cada um com a sua série.\n- QR Code na versão 3, sem CSC; CSC opcional em `PUT /v1/nfce/csc/{empresa_id}`,\n  usado só se a UF recusar a versão 3.\n- Cupom de 80 mm em PDF e em texto de 48 colunas (`GET /v1/nfce/{id}/danfe`).\n- Cancelamento em fila própria, com `cancelavel_ate` na nota e erro\n  `cancelamento_fora_do_prazo`.\n- Itens de prontidão `caixa`, `csc`, `nfce_uf` e `nfce_producao`.\n- Webhooks `NFCE_AUTORIZADA`, `NFCE_REJEITADA`, `NFCE_DENEGADA`, `NFCE_CANCELADA`,\n  `NFCE_DESCARTADA`, `NFCE_DESCARTE_PROXIMO` e `NFCE_ENVIO_PAUSADO`.\n- SDKs TypeScript e PHP (`nfce`, `caixas`) e quatro ferramentas de leitura no MCP.\n- Guia: [Emissão de NFC-e](#tag/emissão-de-nfc-e).\n\n**Acrescentado (NF-e)**\n- `chave_referenciada` no modo `informado`, obrigatória na devolução e na complementar\n  (erro `chave_referenciada_obrigatoria`), e `item_referenciado` no item.\n\n### 17/10/2026\n\n**Acrescentado (NF-e, contingência)**\n- Política de contingência por empresa (`politica_contingencia`: `esperar`, `svc`,\n  `epec`) no perfil fiscal; SVC-AN/SVC-RS e EPEC só para a nota que nunca saiu.\n- Status `contingencia_epec`, objeto `contingencia` na nota, `falha_envio.motivo`\n  `uf_indisponivel`, e o DANFE da nota com EPEC registrado.\n- `GET /v1/sefaz/status` e os webhooks `SEFAZ_STATUS_ALTERADO` e `NFE_CONTINGENCIA`.\n- Simulador: `uf_indisponivel`, `uf_indisponivel_svc_ativo`, `epec_pendente`, `epec_rejeitado`.\n\n**Acrescentado (NF-e)**\n- `falha_envio.motivo` `envio_pausado` e `falha_envio.pausado_em`, e o webhook\n  `NFE_ENVIO_PAUSADO`: depois de recusas seguidas do certificado, a Sudrel para de\n  reenviar até o certificado passar no teste.\n\n### 16/10/2026\n\n**Acrescentado (motor fiscal da NF-e, Bahia ampliada)**\n- Termo de Acordo de atacadista (Decreto 7.799/2000): `termo_acordo` no perfil\n  da empresa e no perfil do produto.\n- ICMS-ST: `st_substituto` no perfil do produto (ICMS10/ICMS70 com MVA do Anexo 1),\n  CST 10 e 70 no modo informado (grupo `st`), ST retida das entradas por vínculo\n  (`/v1/produtos/{codigo}/vinculos-entrada`) e `st_retido` no item do modo calcular.\n- 7% para ME/EPP com o desconto expresso, e o porte do destinatário pela consulta\n  de CNPJ.\n- `exclui_icms_base_pis_cofins` no perfil da empresa.\n- GTIN conferido na SEFAZ (`gtin_sefaz`, erro `gtin_ncm_divergente`).\n- `fcp` no ICMS20 do modo informado.\n\n**Mudou (decisão registrada)**\n- A chave de sandbox passa a cadastrar e aprovar produtos e perfis, num cadastro\n  só dela (antes: 403). O cadastro de produção não muda.\n\n**Acrescentado (motor fiscal da NF-e)**\n- Cadastro de produtos (`/v1/produtos`) com NCM, CEST e GTIN validados nas tabelas\n  oficiais, e perfil fiscal aprovado por uma pessoa.\n- Perfil fiscal da empresa (`/v1/nfe/perfil-fiscal/{empresa_id}`).\n- Modos `calcular` e `conferir` em `POST /v1/nfe` e `POST /v1/nfe/previas`, com\n  `operacao`, `fora_de_cobertura` e cada valor calculado em `ajustes` com regra,\n  versão e fonte.\n- Grupo `ipi` no item do modo informado.\n\n**Acrescentado**\n- Emissão de NF-e modelo 55 (`/v1/nfe`) no modo informado: emissão, prévia,\n  consulta, lista, XML, DANFE, correção, descarte, cancelamento, carta de\n  correção, inutilizações e prontidão, na homologação (sandbox) e na\n  produção da SEFAZ.\n- Webhooks `NFE_AUTORIZADA`, `NFE_REJEITADA`, `NFE_DENEGADA`, `NFE_CANCELADA`,\n  `NFE_CARTA_CORRECAO_REGISTRADA`, `NFE_DESCARTADA` e `NFE_DESCARTE_PROXIMO`.\n- Cenários de NF-e no simulador de falhas.\n\n### 03/10/2026\n\n**Documentação**\n- Nova organização por tarefa: \"O que você quer fazer?\", regras de integração,\n  idempotência, erros e status HTTP, estados da NFS-e, prontidão, paginação,\n  receitas, problemas comuns, glossário.\n- Respostas de erro documentadas rota a rota, com os dois formatos (problem+json\n  e NestJS), inclusive 401 e 429.\n- Documentação também em espanhol (`/docs/es`) e inglês (`/docs/en`).\n- Especificação OpenAPI publicada também em YAML (`/docs/openapi.yaml`) e\n  índice para assistentes de IA em `/docs/llms.txt`.\n\n### 02/10/2026\n\n**Acrescentado**\n- Lote pela API: `POST /v1/lotes` (JSON ou planilha, até 5.000 itens),\n  consulta, itens, relatório, emissão manual e reprocessamento. Webhook\n  `LOTE_EMISSAO_CONCLUIDO`.\n- Log de eventos `GET /v1/eventos`, com cursor e retenção de 90 dias.\n- Webhooks pela API (`/v1/webhooks`): assinatura `X-Sudrel-Signature-V2` com\n  horário, `X-Sudrel-Event-Id` e `X-Sudrel-Delivery-Id`, retentativa por 72\n  horas, troca de segredo com 24 horas de convivência, reenvio, cabeçalhos\n  próprios e webhook de teste separado do de produção.\n- Simulador de falhas (`X-Sudrel-Simular`) com a chave de teste.\n- Log de requisições da API no painel (**Integrações › Log da API**), por 30\n  dias.\n- Prontidão da empresa (`GET /v1/companies/{id}/prontidao`), 412\n  `empresa_nao_pronta` e webhook `EMPRESA_PRONTIDAO_ALTERADA`.\n- Webhook `NFSE_FALHA_TRANSMISSAO`.\n- Parâmetros oficiais do município (`GET /v1/municipios/{ibge}/parametros`).\n- IBS e CBS na DPS do regime regular, e `GET /v1/servicos/{codigo}/nbs`.\n- Substituição de NFS-e (bloco `substituicao` em `POST /v1/nfse`) e dados da\n  obra (`servico.obra`).\n\n**Alterado**\n- O cursor de `GET /v1/eventos` (`proximo_cursor`, `seq` e\n  `cursor_mais_antigo`) passou a ser um texto opaco. O cursor numérico antigo\n  continua aceito em `apos`.\n\n### 01/10/2026\n\n**Acrescentado**\n- Chave de teste `sdr_test_`: emite de verdade na produção restrita do Sistema\n  Nacional, sem valor fiscal e sem cobrar.\n- Status `aguardando_confirmacao`, `POST /v1/nfse/{id}/confirmacao` e webhook\n  `NFSE_AGUARDANDO_CONFIRMACAO`.\n- Aviso `processamento_prolongado` e webhook `NFSE_PROCESSAMENTO_PROLONGADO`.\n\n### 30/09/2026\n\n**Acrescentado**\n- Emissão de NFS-e pela API: `POST /v1/nfse`, `POST /v1/nfse/validacoes`,\n  `GET /v1/nfse`, `GET /v1/nfse/{id}`, XML, PDF e cancelamento. Erros em\n  problem+json, `Idempotency-Key`, `Prefer: wait=N`, `ajustes` e linha do\n  tempo em `eventos`. Webhooks `NFSE_AUTORIZADA`, `NFSE_REJEITADA` e\n  `NFSE_CANCELADA`.\n"
    }
  ],
  "paths": {
    "/v1/account": {
      "get": {
        "tags": [
          "Conta"
        ],
        "operationId": "obterConta",
        "summary": "Dados da conta atual",
        "description": "Identifica a conta dona da chave de API usada na requisição.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conta"
                },
                "example": {
                  "id": "5f9a1c2e-7b3d-4e11-9c2a-1a2b3c4d5e6f",
                  "nome": "Empresa Exemplo LTDA",
                  "status": "ATIVA",
                  "ambiente": "PRODUCAO",
                  "criadaEm": "2026-03-10T13:22:00.000Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/cnpj/{cnpj}": {
      "get": {
        "tags": [
          "Conta"
        ],
        "operationId": "consultarCnpj",
        "summary": "Dados cadastrais de um CNPJ",
        "description": "Confere os dígitos verificadores (vale o CNPJ alfanumérico) e devolve a\nrazão social e o endereço cadastral, os mesmos que a emissão usa para\npreencher o tomador sozinha. Consulta repetida sai do cache da Sudrel.\n`encontrado: false` quando o CNPJ é válido mas a consulta cadastral não\ntrouxe dados.\n",
        "parameters": [
          {
            "name": "cnpj",
            "in": "path",
            "required": true,
            "description": "CNPJ com ou sem pontuação.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "cnpj": "11222333000181",
                  "valido": true,
                  "encontrado": true,
                  "razao_social": "Empresa Exemplo LTDA",
                  "endereco": {
                    "logradouro": "Rua Exemplo",
                    "numero": "100",
                    "complemento": null,
                    "bairro": "Centro",
                    "cep": "01001000",
                    "municipio": "São Paulo",
                    "municipio_ibge": "3550308",
                    "uf": "SP"
                  }
                }
              }
            }
          },
          "400": {
            "description": "CNPJ inválido (posições ou dígitos verificadores)."
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "tags": [
          "Conta"
        ],
        "operationId": "obterConsumo",
        "summary": "Consumo do ciclo de cobrança atual",
        "description": "Franquia, consumo e excedente do ciclo em andamento. A chave de teste\nde emissão (`sdr_test_...`) vê o mesmo consumo da conta; nota de teste\nnunca entra na franquia.\n",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Consumo"
                },
                "example": {
                  "temCicloAtivo": true,
                  "ciclo": {
                    "id": "b7f63b53-584e-4e3c-ac1f-dcf47d1188f9",
                    "status": "ATIVO",
                    "dataInicio": "2026-07-17T16:50:46.690Z",
                    "dataFim": "2026-08-16T16:50:46.690Z",
                    "plano": {
                      "id": "cb898015-0152-4d5b-8de4-7a4a5d34c860",
                      "nome": "Growth",
                      "precoMensal": "349",
                      "franquiaEventos": 2000,
                      "precoUnitarioExcedente": "0.19"
                    }
                  },
                  "franquiaEventos": 2000,
                  "eventosIncluidos": 340,
                  "eventosExcedentes": 0,
                  "saldoExcedenteAberto": 0,
                  "limiteExcedenteAberto": 174.5,
                  "porEmpresa": [
                    {
                      "empresaId": "0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00",
                      "quantidade": 340
                    }
                  ],
                  "pausadaPorExcedente": false,
                  "destravaDisponivel": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/companies": {
      "get": {
        "tags": [
          "Empresas"
        ],
        "operationId": "listarEmpresas",
        "summary": "Lista as empresas da conta",
        "description": "Empresas da conta. A chave de teste de emissão também lista, pra saber em nome de qual empresa emitir o teste.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Empresa"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      },
      "post": {
        "tags": [
          "Empresas"
        ],
        "operationId": "criarEmpresa",
        "summary": "Cadastra uma empresa (CNPJ) para monitoramento",
        "description": "Cadastra o CNPJ na conta. Ele nasce em estado `DRAFT` (produção) —\no próximo passo é enviar o certificado A1 em\n`POST /companies/{id}/certificate`. A chave de teste de emissão não\ncadastra empresa (403).\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CriarEmpresaRequest"
              },
              "example": {
                "cnpj": "12345678000195",
                "nomeExibicao": "Filial São Paulo"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Empresa"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/RequisicaoInvalida"
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/ChaveDeTesteRecusada"
          },
          "409": {
            "description": "Este CNPJ já está cadastrado em outra conta Sudrel.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                },
                "example": {
                  "statusCode": 409,
                  "message": "Este CNPJ já está associado a outra conta. Solicite a transferência pelo atendimento.",
                  "error": "Conflict"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/companies/{id}": {
      "get": {
        "tags": [
          "Empresas"
        ],
        "operationId": "detalharEmpresa",
        "summary": "Detalhe de uma empresa",
        "parameters": [
          {
            "$ref": "#/components/parameters/EmpresaId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Empresa"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/NaoEncontrado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      },
      "delete": {
        "tags": [
          "Empresas"
        ],
        "operationId": "removerEmpresa",
        "summary": "Solicita a remoção da empresa",
        "description": "Inicia a remoção definitiva da empresa. Uma vez que ela já foi\nmonitorada de verdade (passou por `ACTIVE`), a remoção é um\nprocesso de dois passos com um período de segurança entre eles,\npra preservar o histórico fiscal — o segundo passo (confirmação)\né feito pelo painel, não pela API pública.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/EmpresaId"
          }
        ],
        "responses": {
          "204": {
            "description": "Remoção solicitada"
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/ChaveDeTesteRecusada"
          },
          "404": {
            "$ref": "#/components/responses/NaoEncontrado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/companies/{id}/prontidao": {
      "get": {
        "tags": [
          "Empresas"
        ],
        "operationId": "prontidaoEmpresa",
        "summary": "O que falta para a empresa emitir",
        "description": "A mesma checagem que `POST /v1/nfse` faz antes de criar a nota.\nCada item vem com `situacao`:\n\n- `bloqueio`: a emissão é recusada com **412** até resolver.\n- `aviso`: emite, mas vale olhar (certificado vencendo, alíquota\n  oficial do município ainda não conhecida para um código de serviço).\n- `ok`.\n\nCom a chave de sandbox (`sdr_test_`) a resposta é a do ambiente de\nteste: plano de Emissão não é exigido, e empresa que emite pelo\nsistema da prefeitura é `bloqueio` (a prefeitura não tem ambiente\nde teste). O webhook `EMPRESA_PRONTIDAO_ALTERADA` avisa quando um\nitem muda.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/EmpresaId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "empresa_id": {
                      "type": "string"
                    },
                    "ambiente": {
                      "type": "string",
                      "enum": [
                        "producao",
                        "sandbox"
                      ]
                    },
                    "situacao": {
                      "type": "string",
                      "enum": [
                        "ok",
                        "aviso",
                        "bloqueio"
                      ],
                      "description": "A pior situação entre os itens."
                    },
                    "itens": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ItemProntidao"
                      }
                    },
                    "verificado_em": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "empresa_id": "0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00",
                  "ambiente": "producao",
                  "situacao": "aviso",
                  "verificado_em": "2026-10-02T12:00:00.000Z",
                  "itens": [
                    {
                      "item": "certificado",
                      "situacao": "aviso",
                      "mensagem": "O certificado digital vence em 12 dias.",
                      "correcao": "Renove o certificado e envie o novo antes do vencimento."
                    },
                    {
                      "item": "regime_tributario",
                      "situacao": "ok",
                      "mensagem": "Regime tributário configurado.",
                      "correcao": null
                    },
                    {
                      "item": "convenio_municipio",
                      "situacao": "ok",
                      "mensagem": "Recife-PE emite pelo Ambiente Nacional.",
                      "correcao": null
                    },
                    {
                      "item": "plano_emissao",
                      "situacao": "ok",
                      "mensagem": "Plano de Emissão ativo.",
                      "correcao": null
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/NaoEncontrado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/servicos/{codigo}/nbs": {
      "get": {
        "tags": [
          "Emissão de NFS-e"
        ],
        "operationId": "nbsDoServico",
        "summary": "NBS admitidos para um código de serviço",
        "description": "Desde 01/10/2026 a NFS-e do regime regular declara o IBS e a CBS (Ato\nConjunto RFB/CGIBS nº 4/2026; Simples Nacional a partir de 01/01/2027), e\ncom eles o NBS do serviço. Esta rota lista os NBS que a tabela oficial\n(Anexo VIII da RTC da NFS-e) admite para o código de tributação nacional,\ncom o tipo de operação (`c_ind_op`) e a classificação tributária\n(`c_class_trib`) que cada um leva. `padrao: true` é o que vai quando nem\na nota nem a empresa escolhem. Classificação com redução (`reducao: true`)\nsó é declarada com a confirmação da empresa; sem ela, vai tributação\nintegral. Quando o tipo de operação exige o endereço do tomador (IBS/CBS\ndevido no domicílio dele), a nota sem endereço volta com o erro\n`tomador_endereco_obrigatorio` antes de ir ao Sistema Nacional. Lista vazia: o código não declara IBS/CBS\npela Sudrel (fora da tabela, ou exige dados que a emissão não coleta).\n",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "description": "Código de tributação nacional, 6 dígitos.",
            "schema": {
              "type": "string",
              "example": "171901"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "nbs": {
                        "type": "string",
                        "example": "113022100"
                      },
                      "descricao": {
                        "type": "string",
                        "example": "Serviços de contabilidade"
                      },
                      "c_ind_op": {
                        "type": "string",
                        "example": "100301"
                      },
                      "c_class_trib": {
                        "type": "string",
                        "example": "200052"
                      },
                      "padrao": {
                        "type": "boolean"
                      },
                      "reducao": {
                        "type": "boolean",
                        "description": "A classificação tem redução de alíquota (CST 200 ou 011). Ela só é\ndeclarada quando a empresa confirma, na configuração fiscal, que\natende os requisitos da LC 214; sem isso a nota declara tributação\nintegral (CST 000, `000001`).\n"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/RequisicaoInvalida"
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/municipios/{ibge}/parametros": {
      "get": {
        "tags": [
          "Emissão de NFS-e"
        ],
        "operationId": "parametrosMunicipio",
        "summary": "Convênio e parâmetros oficiais de um município",
        "description": "O que a Sudrel sabe do município a partir do Sistema Nacional:\nse ele emite pelo Ambiente Nacional e os parâmetros oficiais já\nconsultados (alíquota do ISS por código de serviço, com vigência, e\nretenções). Não dispara consulta nova: devolve o que está guardado,\ncom a data da consulta.\n\nA chave de cada alíquota é o código de serviço da parametrização do\nSistema Nacional: código de tributação nacional com pontos mais os 3\ndígitos do código de tributação municipal (ex.: `14.06.01.501`).\n",
        "parameters": [
          {
            "name": "ibge",
            "in": "path",
            "required": true,
            "description": "Código IBGE do município, 7 dígitos.",
            "schema": {
              "type": "string",
              "example": "2611606"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "municipio": {
                      "type": "object",
                      "properties": {
                        "codigo_ibge": {
                          "type": "string"
                        },
                        "nome": {
                          "type": "string"
                        },
                        "uf": {
                          "type": "string"
                        }
                      }
                    },
                    "convenio": {
                      "type": "object",
                      "properties": {
                        "aderiu_ambiente_nacional": {
                          "type": "boolean"
                        },
                        "fonte": {
                          "type": "string",
                          "enum": [
                            "api_oficial",
                            "consulta_ao_vivo",
                            "snapshot_local"
                          ],
                          "description": "De onde veio a informação do convênio."
                        },
                        "conferido_em": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        }
                      }
                    },
                    "parametros": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "tipo": {
                            "type": "string",
                            "enum": [
                              "aliquota",
                              "retencoes"
                            ]
                          },
                          "chave": {
                            "type": "string",
                            "example": "14.06.01.501"
                          },
                          "tem_dados": {
                            "type": "boolean",
                            "description": "`false`: o Sistema Nacional respondeu que não há parâmetro."
                          },
                          "dados": {
                            "type": "object"
                          },
                          "vigencia_inicio": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          },
                          "vigencia_fim": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          },
                          "consultado_em": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "municipio": {
                    "codigo_ibge": "2611606",
                    "nome": "Recife",
                    "uf": "PE"
                  },
                  "convenio": {
                    "aderiu_ambiente_nacional": true,
                    "fonte": "api_oficial",
                    "conferido_em": "2026-10-02T06:00:00.000Z"
                  },
                  "parametros": [
                    {
                      "tipo": "aliquota",
                      "chave": "14.06.01.501",
                      "tem_dados": true,
                      "dados": {
                        "vigencias": [
                          {
                            "incidencia": "SIM",
                            "aliquota": 5,
                            "inicio": "2025-10-16",
                            "fim": null
                          }
                        ]
                      },
                      "vigencia_inicio": "2025-10-16T00:00:00.000Z",
                      "vigencia_fim": null,
                      "consultado_em": "2026-10-02T06:00:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/RequisicaoInvalida"
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/NaoEncontrado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/companies/{id}/certificate": {
      "post": {
        "tags": [
          "Empresas"
        ],
        "operationId": "enviarCertificado",
        "summary": "Envia (ou troca) o certificado digital A1 da empresa",
        "description": "Multipart/form-data com o arquivo `.pfx`/`.p12` no campo\n`certificado` e a senha no campo `senha`. O certificado precisa ser\no e-CNPJ da própria empresa cadastrada — certificados de outro CNPJ\nsão rejeitados. A chave de teste de emissão não envia certificado (403).\n\nSe a empresa já estiver ativa e monitorando (certificado vencendo\nou revogado), enviar um novo aqui só troca o material — o\nmonitoramento continua de onde parou, sem reiniciar a análise de\nhistórico.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/EmpresaId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "certificado",
                  "senha"
                ],
                "properties": {
                  "certificado": {
                    "type": "string",
                    "format": "binary",
                    "description": "Arquivo do certificado A1 (.pfx ou .p12), até 10MB."
                  },
                  "senha": {
                    "type": "string",
                    "description": "Senha do certificado."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Certificado aceito",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Empresa"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/RequisicaoInvalida"
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/ChaveDeTesteRecusada"
          },
          "404": {
            "$ref": "#/components/responses/NaoEncontrado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/companies/{id}/pause": {
      "post": {
        "tags": [
          "Empresas"
        ],
        "operationId": "pausarEmpresa",
        "summary": "Pausa o monitoramento da empresa",
        "description": "Nenhuma consulta nova é feita ao Ambiente de Dados Nacional até reativar.",
        "parameters": [
          {
            "$ref": "#/components/parameters/EmpresaId"
          }
        ],
        "responses": {
          "201": {
            "description": "Pausada",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "pausada": {
                      "type": "boolean",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/ChaveDeTesteRecusada"
          },
          "404": {
            "$ref": "#/components/responses/NaoEncontrado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/companies/{id}/resume": {
      "post": {
        "tags": [
          "Empresas"
        ],
        "operationId": "retomarEmpresa",
        "summary": "Retoma o monitoramento da empresa",
        "description": "Volta a consultar o Ambiente de Dados Nacional a partir do último NSU confirmado — nunca reprocessa notas já vistas.",
        "parameters": [
          {
            "$ref": "#/components/parameters/EmpresaId"
          }
        ],
        "responses": {
          "201": {
            "description": "Retomada",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "retomada": {
                      "type": "boolean",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/ChaveDeTesteRecusada"
          },
          "404": {
            "$ref": "#/components/responses/NaoEncontrado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/documents": {
      "get": {
        "tags": [
          "Documentos"
        ],
        "operationId": "listarDocumentos",
        "summary": "Lista notas fiscais",
        "description": "Lista paginada por cursor, com filtros combináveis.",
        "parameters": [
          {
            "name": "cnpjs",
            "in": "query",
            "description": "Um ou vários CNPJs separados por vírgula. Ausente = todos os CNPJs da conta.",
            "schema": {
              "type": "string"
            },
            "example": "12345678000190,98765432000110"
          },
          {
            "name": "situacao",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/SituacaoNota"
            }
          },
          {
            "name": "papel",
            "in": "query",
            "description": "Ausente = respeita o escopo de monitoramento configurado em cada empresa.",
            "schema": {
              "$ref": "#/components/schemas/PapelNota"
            }
          },
          {
            "name": "prestador",
            "in": "query",
            "description": "Filtra por CNPJ/CPF ou nome do prestador (contém, sem diferenciar maiúsculas).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "numero",
            "in": "query",
            "description": "Número da nota (contém).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "chaveAcesso",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "valorMinCentavos",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "name": "valorMaxCentavos",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "name": "dataInicio",
            "in": "query",
            "description": "Filtra por data de emissão (ISO 8601), início do intervalo.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "dataFim",
            "in": "query",
            "description": "Filtra por data de emissão (ISO 8601), fim do intervalo.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "tipoDocumento",
            "in": "query",
            "description": "Sem ele, a lista mistura NFS-e, NF-e e CT-e.",
            "schema": {
              "$ref": "#/components/schemas/TipoDocumentoFiscal"
            }
          },
          {
            "name": "ordenarPor",
            "in": "query",
            "description": "`dataEmissao` (padrão) ou `recebidaEm` (o que a Sudrel capturou por último; uma NFS-e pode chegar hoje com data de emissão de dias atrás).",
            "schema": {
              "type": "string",
              "enum": [
                "dataEmissao",
                "recebidaEm"
              ]
            }
          },
          {
            "name": "cicloCobranca",
            "in": "query",
            "description": "`atual`: só os documentos cobrados no ciclo atual de Recebidas. Ignora a data de emissão: o ciclo conta pela chegada.",
            "schema": {
              "type": "string",
              "enum": [
                "atual"
              ]
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "`proximoCursor` da página anterior (hoje, o id do último item). Guarde e devolva sem interpretar.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "itens": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/NotaResumo"
                      }
                    },
                    "proximoCursor": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                },
                "example": {
                  "itens": [
                    {
                      "id": "8a1b2c3d-4e5f-6789-abcd-ef0123456789",
                      "numero": "1024",
                      "nsu": "720",
                      "chaveAcesso": "35260712345678000190550010000010241123456789",
                      "prestador": {
                        "documento": "12345678000190",
                        "nome": "Prestador Exemplo LTDA"
                      },
                      "cnpjTomador": "98765432000110",
                      "papel": "RECEBIDA",
                      "valorServicos": "1500.00",
                      "situacao": "AUTORIZADA",
                      "dataEmissao": "2026-07-15T10:30:00.000Z",
                      "recebidaEm": "2026-07-15T10:31:12.000Z",
                      "quantidadeEventos": 0
                    }
                  ],
                  "proximoCursor": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/ChaveDeTesteRecusada"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/documents/{id}": {
      "get": {
        "tags": [
          "Documentos"
        ],
        "operationId": "detalharDocumento",
        "summary": "Detalhe de uma nota fiscal",
        "description": "Inclui o XML original e a linha do tempo de eventos (cancelamento, substituição etc.).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotaDetalhe"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/ChaveDeTesteRecusada"
          },
          "404": {
            "$ref": "#/components/responses/NaoEncontrado"
          },
          "429": {
            "$ref": "#/components/responses/LimiteRequisicoes"
          }
        }
      }
    },
    "/v1/nfse": {
      "post": {
        "tags": [
          "Emissão de NFS-e"
        ],
        "operationId": "emitirNfse",
        "summary": "Emite uma NFS-e",
        "description": "Valida, cria e transmite a nota. Se a empresa ainda não pode emitir\n(sem certificado válido, sem regime tributário, conta sem plano de\nEmissão), devolve **412** `empresa_nao_pronta` com a mesma lista de\n`GET /v1/companies/{id}/prontidao` e não cria nada. Com payload\ninválido devolve **422 com todos os erros** e não cria nada. Com\npayload válido, a nota\nentra na fila de emissão e a chamada acompanha o resultado pelo\ntempo pedido em `Prefer: wait=N`:\n\n- **201**: autorizada dentro do prazo. Corpo: a nota.\n- **202**: ainda `transmitindo`. Corpo: a nota; acompanhe por\n  `Location` ou pelo webhook `NFSE_AUTORIZADA`.\n- **422** `nfse_rejeitada`: rejeitada pelo Sistema Nacional. O corpo\n  traz `nfse_id` e a nota inteira.\n- **422** `falha_transmissao`: a transmissão terminou sem confirmação\n  dentro da espera. O corpo traz `nfse_id` e a nota inteira; veja\n  `falha.dps_enviada` antes de emitir de novo.\n\n**202 não é erro.** A nota existe e está sendo cuidada: acompanhe por\nwebhook ou por `GET /v1/nfse/{id}`. Repetir a chamada com a mesma\n`Idempotency-Key` devolve a MESMA resposta gravada (a foto do momento,\nque pode continuar `transmitindo` mesmo depois de a nota autorizar):\npara saber o status atual, use o `GET`.\n\nUse sempre `Idempotency-Key`. Repetir a MESMA chave com o MESMO\ncorpo devolve a mesma resposta, sem criar outra nota; a mesma chave\ncom corpo diferente é **409** `idempotencia_conflito`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/PreferWait"
          },
          {
            "$ref": "#/components/parameters/SimularFalha"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NfseEntrada"
              },
              "examples": {
                "minima": {
                  "summary": "Emissão mínima (o resto vem da configuração da empresa)",
                  "value": {
                    "empresa_id": "0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00",
                    "referencia": "PED-1001",
                    "tomador": {
                      "documento": "11222333000181"
                    },
                    "valor": "1500.00",
                    "servico": {
                      "descricao": "Consultoria em sistemas, setembro/2026"
                    }
                  }
                },
                "comRetencoes": {
                  "summary": "Com retenções e alíquota de ISS",
                  "value": {
                    "empresa_id": "0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00",
                    "referencia": "PED-1002",
                    "modelo": "Mensalidade",
                    "tomador": {
                      "documento": "11222333000181",
                      "email": "financeiro@cliente.com.br"
                    },
                    "valor": "1500.00",
                    "retencoes": {
                      "iss": true,
                      "pis": {
                        "aliquota": "0.65"
                      },
                      "cofins": {
                        "aliquota": "3"
                      },
                      "csll": {
                        "aliquota": "1"
                      }
                    },
                    "iss": {
                      "aliquota": "2"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Autorizada.",
            "headers": {
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "`/v1/nfse/{id}`"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfse"
                },
                "examples": {
                  "autorizada": {
                    "$ref": "#/components/examples/NfseAutorizada"
                  }
                }
              }
            }
          },
          "202": {
            "description": "Aceita e ainda transmitindo.",
            "headers": {
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "`/v1/nfse/{id}`"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "403": {
            "description": "Chave restrita a outra empresa.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "404": {
            "description": "`nao_encontrado`: `empresa_id` não existe nesta conta.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "409": {
            "description": "`referencia_duplicada` (com `nfse_id` da nota existente),\n`idempotencia_conflito` (mesma `Idempotency-Key` com outro corpo) ou\n`conflito` (a mesma `Idempotency-Key` ainda está em processamento em\noutra requisição: espere a primeira responder e repita).\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                },
                "example": {
                  "type": "https://sudrel.com.br/docs/erros/referencia_duplicada",
                  "codigo": "referencia_duplicada",
                  "codigo_oficial": null,
                  "campo": "/referencia",
                  "mensagem": "Já existe uma nota com esta referência nesta empresa.",
                  "correcao": "Consulte a nota existente em GET /v1/nfse/9d2f0c1e-3a4b-4c5d-8e9f-0a1b2c3d4e5f. Se quiser emitir outra nota, use outra referência.",
                  "retentavel": false,
                  "nfse_id": "9d2f0c1e-3a4b-4c5d-8e9f-0a1b2c3d4e5f",
                  "requisicao_id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e"
                }
              }
            }
          },
          "412": {
            "description": "`empresa_nao_pronta`: a empresa ainda não pode emitir. Nenhuma\nnota foi criada. `itens` traz a prontidão inteira; resolva os de\n`\"situacao\": \"bloqueio\"` e envie de novo.\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                },
                "example": {
                  "type": "https://sudrel.com.br/docs/erros/empresa_nao_pronta",
                  "codigo": "empresa_nao_pronta",
                  "codigo_oficial": null,
                  "campo": "/empresa_id",
                  "mensagem": "A empresa ainda não pode emitir: A empresa não tem certificado digital A1 ativo.",
                  "correcao": "Envie o certificado pelo painel ou por POST /v1/companies/{id}/certificate.",
                  "retentavel": false,
                  "requisicao_id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e",
                  "itens": [
                    {
                      "item": "certificado",
                      "situacao": "bloqueio",
                      "mensagem": "A empresa não tem certificado digital A1 ativo.",
                      "correcao": "Envie o certificado pelo painel ou por POST /v1/companies/{id}/certificate."
                    },
                    {
                      "item": "regime_tributario",
                      "situacao": "ok",
                      "mensagem": "Regime tributário configurado.",
                      "correcao": null
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "`validacao`: payload inválido, com todos os erros em `erros`\n(nada foi criado). `nfse_rejeitada`: rejeitada pelo Sistema\nNacional (a nota existe, com status `rejeitada`).\n`falha_transmissao`: a nota existe e a transmissão não pôde ser\nconcluída. `simulacao_so_no_sandbox` / `simulacao_invalida`: o\ncabeçalho `X-Sudrel-Simular` foi mandado com a chave de produção ou\ncom um cenário que não existe.\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                },
                "examples": {
                  "validacao": {
                    "summary": "Payload inválido",
                    "value": {
                      "type": "https://sudrel.com.br/docs/erros/validacao",
                      "codigo": "validacao",
                      "codigo_oficial": null,
                      "campo": null,
                      "mensagem": "A nota tem 2 erros e não foi criada.",
                      "correcao": "Corrija os itens de \"erros\" e envie de novo. Nenhuma nota foi criada nem número de DPS reservado.",
                      "retentavel": false,
                      "requisicao_id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e",
                      "erros": [
                        {
                          "type": "https://sudrel.com.br/docs/erros/tipo_invalido",
                          "codigo": "tipo_invalido",
                          "codigo_oficial": null,
                          "campo": "/valor",
                          "mensagem": "Esperado texto, recebido número.",
                          "correcao": "Envie o valor entre aspas, ex.: \"1500.00\".",
                          "retentavel": false
                        },
                        {
                          "type": "https://sudrel.com.br/docs/erros/tomador_igual_prestador",
                          "codigo": "tomador_igual_prestador",
                          "codigo_oficial": "E0202",
                          "campo": "/tomador/documento",
                          "mensagem": "O tomador não pode ser a própria empresa emissora.",
                          "correcao": "Informe o CPF/CNPJ de quem recebeu o serviço.",
                          "retentavel": false
                        }
                      ]
                    }
                  },
                  "rejeitada": {
                    "summary": "Rejeitada pelo Sistema Nacional",
                    "value": {
                      "type": "https://sudrel.com.br/docs/erros/nfse_rejeitada",
                      "codigo": "nfse_rejeitada",
                      "codigo_oficial": "E0039",
                      "campo": null,
                      "mensagem": "E0039: O município emissor informado na DPS deve estar parametrizado para utilizar os emissores públicos nacionais.",
                      "correcao": "Corrija o dado apontado na mensagem e emita uma nota nova. Esta nota fica registrada como rejeitada.",
                      "retentavel": false,
                      "nfse_id": "9d2f0c1e-3a4b-4c5d-8e9f-0a1b2c3d4e5f",
                      "requisicao_id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e",
                      "nfse": {
                        "status": "rejeitada"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      },
      "get": {
        "tags": [
          "Emissão de NFS-e"
        ],
        "operationId": "listarNfse",
        "summary": "Lista as NFS-e emitidas",
        "description": "Mais recente primeiro, paginada por cursor. Uma página pode vir com\nmenos itens que `limite` e ainda ter `proximo_cursor` quando o\nfiltro é `transmitindo` ou `falha_transmissao`: continue até\n`proximo_cursor` vir nulo.\n",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "transmitindo",
                "autorizada",
                "rejeitada",
                "cancelada",
                "falha_transmissao",
                "descartada",
                "aguardando_confirmacao"
              ]
            }
          },
          {
            "name": "tomador",
            "in": "query",
            "description": "CPF ou CNPJ do tomador.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "referencia",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "criada_de",
            "in": "query",
            "description": "Data ISO 8601, inclusive.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "criada_ate",
            "in": "query",
            "description": "Data ISO 8601, inclusive.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "description": "1 a 100, padrão 50. Valor fora da faixa é ajustado para dentro dela, sem erro.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "`proximo_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Nfse"
                      }
                    },
                    "proximo_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/nfse/validacoes": {
      "post": {
        "tags": [
          "Emissão de NFS-e"
        ],
        "operationId": "validarNfse",
        "summary": "Valida uma NFS-e sem emitir",
        "description": "Exatamente a mesma validação e normalização de `POST /v1/nfse`,\nsem criar nota, sem reservar número de DPS e sem transmitir. Devolve\na nota como ela seria emitida, os `ajustes`, todos os erros e a\nprontidão da empresa. `valida` só é `true` se não houver erro nem\nitem de prontidão com `bloqueio`.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NfseEntrada"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado da validação (válida ou não).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "valida": {
                      "type": "boolean"
                    },
                    "empresa_id": {
                      "type": "string",
                      "nullable": true
                    },
                    "referencia": {
                      "type": "string",
                      "nullable": true
                    },
                    "nota": {
                      "type": "object",
                      "nullable": true,
                      "description": "Mesmas seções de conteúdo de `Nfse` (valor, tomador, serviço, retenções, apuração própria, ISS)."
                    },
                    "ajustes": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Ajuste"
                      }
                    },
                    "erros": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ErroCampo"
                      }
                    },
                    "prontidao": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "situacao": {
                          "type": "string",
                          "enum": [
                            "ok",
                            "aviso",
                            "bloqueio"
                          ]
                        },
                        "itens": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ItemProntidao"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/nfse/{id}": {
      "get": {
        "tags": [
          "Emissão de NFS-e"
        ],
        "operationId": "consultarNfse",
        "summary": "Consulta uma NFS-e",
        "description": "`{id}` aceita o id Sudrel, a sua `referencia` ou a chave de acesso.\nSe a mesma referência existir em duas empresas da conta, informe\n`empresa_id` (sem ele a resposta é 409 `referencia_ambigua`).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfseId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfse"
                },
                "examples": {
                  "autorizada": {
                    "$ref": "#/components/examples/NfseAutorizada"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "description": "Nota não encontrada nesta conta.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/nfse/{id}/xml": {
      "get": {
        "tags": [
          "Emissão de NFS-e"
        ],
        "operationId": "baixarXmlNfse",
        "summary": "XML da NFS-e",
        "description": "XML de retorno do Sistema Nacional (ou o XML enviado, se ainda não houver retorno).",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfseId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "description": "Só quando a mesma `referencia` existe em duas empresas.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "description": "`nfse_nao_encontrada`, ou `nao_encontrado` quando a nota ainda não tem XML.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/nfse/{id}/pdf": {
      "get": {
        "tags": [
          "Emissão de NFS-e"
        ],
        "operationId": "baixarPdfNfse",
        "summary": "PDF (DANFSe) da NFS-e",
        "description": "Só existe para nota autorizada ou cancelada (a cancelada sai com a tarja).",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfseId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "description": "Só quando a mesma `referencia` existe em duas empresas.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfseNaoEncontrada"
          },
          "409": {
            "description": "`nfse_sem_pdf` (`retentavel: true`): a nota ainda não foi autorizada, ou o PDF ainda está sendo gerado. `referencia_ambigua`: informe `empresa_id`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/nfse/{id}/confirmacao": {
      "post": {
        "tags": [
          "Emissão de NFS-e"
        ],
        "operationId": "confirmarNfse",
        "summary": "Confirma a transmissão de uma nota que espera confirmação",
        "description": "Para nota em `aguardando_confirmacao` (a competência acabou antes de\numa retentativa automática). Sem corpo, emite com a competência\noriginal; com `competencia`, troca antes de emitir (mês atual ou\nanterior). A nota volta para `transmitindo`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfseId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "description": "Só quando a mesma `referencia` existe em duas empresas.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "competencia": {
                    "type": "string",
                    "example": "2026-10"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Confirmada; a nota volta à fila.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfseNaoEncontrada"
          },
          "409": {
            "description": "`nfse_nao_aguarda_confirmacao`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "`validacao`, com `erros[0].codigo` = `competencia_invalida`: a competência pedida não é o mês atual nem o anterior.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/nfse/{id}/cancelamento": {
      "post": {
        "tags": [
          "Emissão de NFS-e"
        ],
        "operationId": "cancelarNfse",
        "summary": "Cancela uma NFS-e autorizada",
        "description": "Evento de cancelamento no Sistema Nacional. Devolve a nota atualizada, com `status` `cancelada` e o protocolo em `cancelamento`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfseId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "description": "Só quando a mesma `referencia` existe em duas empresas.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "motivo",
                  "justificativa"
                ],
                "properties": {
                  "motivo": {
                    "type": "string",
                    "enum": [
                      "erro_emissao",
                      "servico_nao_prestado",
                      "outros"
                    ]
                  },
                  "justificativa": {
                    "type": "string",
                    "minLength": 15,
                    "maxLength": 255
                  }
                }
              },
              "example": {
                "motivo": "servico_nao_prestado",
                "justificativa": "Pedido cancelado pelo cliente antes da entrega."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cancelada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfseNaoEncontrada"
          },
          "422": {
            "description": "`validacao` (`motivo_invalido`, ou `justificativa_invalida`: de 15 a 255 caracteres) ou `cancelamento_recusado` (o Sistema Nacional recusou o evento; o motivo vem em `mensagem`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/nfe": {
      "post": {
        "tags": [
          "Emissão de NF-e"
        ],
        "operationId": "emitirNfe",
        "summary": "Emite uma NF-e (modelo 55)",
        "description": "Tributos informados pelo seu ERP (`modo: \"informado\"`, o padrão) ou\ncalculados pela Sudrel a partir do produto cadastrado (`modo: \"calcular\"`;\nveja **Produtos e motor fiscal**). A Sudrel valida\ntudo antes de reservar número: erros de campo voltam juntos em 422\n`validacao`, cada um no seu JSON Pointer; totais que não fecham com a soma\ndos itens também. Empresa sem os requisitos da NF-e é 412\n`empresa_nao_pronta` (veja `GET /v1/nfe/prontidao/{empresa_id}`).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/PreferWait"
          },
          {
            "$ref": "#/components/parameters/SimularFalhaNfe"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NfeEntrada"
              },
              "examples": {
                "calcular": {
                  "$ref": "#/components/examples/NfeEntradaCalcular"
                },
                "venda": {
                  "$ref": "#/components/examples/NfeEntradaVenda"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Autorizada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfe"
                },
                "examples": {
                  "autorizada": {
                    "$ref": "#/components/examples/NfeAutorizada"
                  }
                }
              }
            }
          },
          "202": {
            "description": "Ainda `transmitindo` ou `aguardando_confirmacao`. Acompanhe por `GET /v1/nfe/{id}` ou pelo webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfe"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "409": {
            "description": "`referencia_duplicada` (a referência já existe nesta empresa; o id da nota existente vem em `nfe_id`) ou a mesma `Idempotency-Key` com outro corpo.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "412": {
            "description": "`empresa_nao_pronta`: as pendências vêm em `itens`, no formato de `GET /v1/nfe/prontidao/{empresa_id}`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "`validacao` (lista em `erros`), `nfe_rejeitada` ou `nfe_denegada` (a nota\ncompleta vem em `nfe`, com `nfe_id`),\n`simulacao_so_no_sandbox`, `simulacao_invalida`, `fora_de_cobertura` (modo\ncalcular: lista em `fora_de_cobertura`; `retentavel: true` quando é a\ncalculadora oficial fora do ar) ou `conferencia_divergente` (modo conferir\ncom a recusa ligada).\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                },
                "examples": {
                  "rejeitada": {
                    "$ref": "#/components/examples/NfeRejeitadaProblema"
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          },
          "503": {
            "description": "`sefaz_limite_consumo`: a cota de consultas da SEFAZ para este CNPJ ou UF chegou ao limite. Tente de novo depois do `Retry-After`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Emissão de NF-e"
        ],
        "operationId": "listarNfe",
        "summary": "Lista as NF-e",
        "description": "Do ambiente da chave (sandbox ou produção), mais novas primeiro, com cursor.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Um status público (`autorizada`, `rejeitada`...).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "referencia",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "destinatario",
            "in": "query",
            "description": "CPF ou CNPJ do destinatário.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "criada_de",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "criada_ate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "O `proximo_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Nfe"
                      }
                    },
                    "proximo_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/nfe/previas": {
      "post": {
        "tags": [
          "Emissão de NF-e"
        ],
        "operationId": "previaNfe",
        "summary": "Valida e mostra o XML sem emitir",
        "description": "Mesmo corpo de `POST /v1/nfe`. Lê, confere os totais, monta o XML e valida\nno esquema oficial, **sem reservar número** e sem ir à SEFAZ. Responde 200\nsempre que o corpo é JSON: `valida` diz se a emissão passaria.\n\nÉ opcional: a emissão faz as mesmas conferências antes de reservar número.\nServe para ver o XML e os `ajustes` antes, ou para validar no seu sistema\nsem criar nota.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NfeEntrada"
              },
              "examples": {
                "calcular": {
                  "$ref": "#/components/examples/NfeEntradaCalcular"
                },
                "venda": {
                  "$ref": "#/components/examples/NfeEntradaVenda"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado da prévia.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NfePrevia"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/sefaz/status": {
      "get": {
        "tags": [
          "Contingência da NF-e"
        ],
        "operationId": "statusSefazNfe",
        "summary": "Estado da SEFAZ de cada UF para a NF-e",
        "description": "UF com emissão nas últimas 24 horas, no ambiente da chave (`sdr_test_` vê a\nhomologação). UF fora da lista está `normal`.\n",
        "parameters": [
          {
            "name": "uf",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "BA"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EstadoUfSefaz"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          }
        }
      }
    },
    "/v1/nfe/prontidao/{empresa_id}": {
      "get": {
        "tags": [
          "Emissão de NF-e"
        ],
        "operationId": "prontidaoNfe",
        "summary": "A empresa está pronta para emitir NF-e?",
        "description": "Itens com `item` estável: `certificado`, `certificado_sefaz` (o certificado\ntestado na SEFAZ da UF antes da primeira nota: `bloqueio` quando ela o recusa),\n`endereco`, `regime_tributario`,\n`inscricao_estadual`, `cadastro_sefaz` (a inscrição conferida na SEFAZ da\nUF), `habilitacao_nfe` (a SEFAZ disse que o CNPJ não está habilitado a\nemitir NF-e, rejeição 203), `escritorio_contabilidade` (aviso nas UFs que\nexigem o escritório no autXML). Qualquer `bloqueio` faz a emissão responder 412.\n",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProntidaoNfe"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "description": "Empresa não encontrada nesta conta.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfe/inutilizacoes": {
      "get": {
        "tags": [
          "Emissão de NF-e"
        ],
        "operationId": "listarInutilizacoesNfe",
        "summary": "Números inutilizados pela Sudrel",
        "description": "Faixas que a Sudrel inutilizou na SEFAZ (notas descartadas e números\nperdidos), com o protocolo e as notas que motivaram cada faixa em `notas`.\n",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/InutilizacaoNfe"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          }
        }
      }
    },
    "/v1/nfe/{id}": {
      "get": {
        "tags": [
          "Emissão de NF-e"
        ],
        "operationId": "consultarNfe",
        "summary": "Consulta uma NF-e",
        "description": "`{id}` aceita o id Sudrel, a sua `referencia` ou a chave de acesso.",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfeId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "description": "Só quando a mesma `referencia` existe em duas empresas.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfe"
                },
                "examples": {
                  "autorizada": {
                    "$ref": "#/components/examples/NfeAutorizada"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfeNaoEncontrada"
          },
          "409": {
            "description": "`referencia_ambigua`: informe `empresa_id`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/nfe/{id}/xml": {
      "get": {
        "tags": [
          "Emissão de NF-e"
        ],
        "operationId": "baixarXmlNfe",
        "summary": "XML autorizado (nfeProc)",
        "description": "O `nfeProc` (NF-e assinada mais o protocolo da SEFAZ). Só para nota `autorizada` ou `cancelada`; nas outras, 409 `nfe_sem_documento`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfeId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "XML.",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfeNaoEncontrada"
          },
          "409": {
            "description": "`nfe_sem_documento`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfe/{id}/danfe": {
      "get": {
        "tags": [
          "Emissão de NF-e"
        ],
        "operationId": "baixarDanfeNfe",
        "summary": "DANFE em PDF",
        "description": "Gerado a partir do XML autorizado. Só para nota `autorizada` ou `cancelada`; nas outras, 409 `nfe_sem_documento`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfeId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "PDF.",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfeNaoEncontrada"
          },
          "409": {
            "description": "`nfe_sem_documento`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfe/{id}/correcao": {
      "post": {
        "tags": [
          "Emissão de NF-e"
        ],
        "operationId": "corrigirNfe",
        "summary": "Corrige uma NF-e rejeitada e reenvia",
        "description": "Só para nota `rejeitada`. O corpo é o pedido completo, como em\n`POST /v1/nfe`; a nota é refeita com o **mesmo número** e transmitida de\nnovo. Se o mês virou desde a reserva, a chave de acesso muda (a anterior\nfica em `chaves_anteriores`), porque a chave carrega o ano e o mês de\nemissão. Responde 200 com a nota autorizada, 202 se ainda transmite, ou 422\n`nfe_rejeitada` de novo. Outro status é 409 `nfe_nao_corrigivel`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfeId"
          },
          {
            "$ref": "#/components/parameters/PreferWait"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NfeEntrada"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Autorizada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfe"
                }
              }
            }
          },
          "202": {
            "description": "Ainda transmitindo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfe"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfeNaoEncontrada"
          },
          "409": {
            "description": "`nfe_nao_corrigivel`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "`validacao` ou `nfe_rejeitada`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfe/{id}/descarte": {
      "post": {
        "tags": [
          "Emissão de NF-e"
        ],
        "operationId": "descartarNfe",
        "summary": "Desiste de uma NF-e rejeitada",
        "description": "A nota vira `descartada` e o número entra na próxima inutilização da Sudrel\n(veja `GET /v1/nfe/inutilizacoes`). Só para nota `rejeitada`; outro status é\n409 `nfe_nao_descartavel`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfeId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "motivo": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "motivo": "Pedido cancelado antes da correção."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Descartada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfe"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfeNaoEncontrada"
          },
          "409": {
            "description": "`nfe_nao_descartavel`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfe/{id}/cancelamento": {
      "post": {
        "tags": [
          "Emissão de NF-e"
        ],
        "operationId": "cancelarNfe",
        "summary": "Cancela uma NF-e autorizada",
        "description": "Evento 110111 na SEFAZ da UF. Prazo de **24 horas** depois da autorização\n(Ajuste SINIEF 07/05, cláusula décima segunda). Pedir de novo uma nota já\ncancelada devolve a nota, sem novo evento. Devolve a nota com `status`\n`cancelada` e o protocolo em `cancelamento`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfeId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "justificativa"
                ],
                "properties": {
                  "justificativa": {
                    "type": "string",
                    "minLength": 15,
                    "maxLength": 255
                  }
                }
              },
              "example": {
                "justificativa": "Pedido cancelado pelo cliente antes do envio."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cancelada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfe"
                }
              }
            }
          },
          "202": {
            "description": "A resposta da SEFAZ ao evento não chegou; a Sudrel consulta e conclui sozinha. Acompanhe pelo webhook `NFE_CANCELADA`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfe"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfeNaoEncontrada"
          },
          "409": {
            "description": "`nfe_nao_cancelavel`: só nota `autorizada` cancela.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "`cancelamento_fora_do_prazo` (passou das 24 horas: só o cancelamento\nextemporâneo, pedido pelo contribuinte direto na SEFAZ),\n`evento_invalido` (justificativa de 15 a 255 caracteres) ou\n`cancelamento_recusado` (a SEFAZ recusou; o `cStat` vem em\n`codigo_oficial`).\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "503": {
            "description": "`sefaz_limite_consumo`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfe/{id}/cartas-correcao": {
      "post": {
        "tags": [
          "Emissão de NF-e"
        ],
        "operationId": "registrarCartaCorrecaoNfe",
        "summary": "Registra uma carta de correção (CC-e)",
        "description": "Evento 110110, até 20 por nota, numeradas em sequência; cada uma substitui\na anterior, então mande o texto completo de tudo o que corrige. A condição\nde uso oficial vai no evento. A resposta traz `aviso`\n`carta_correcao_limites` com o que a carta não pode corrigir: a Sudrel não\nlê o texto e não bloqueia.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfeId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "correcao"
                ],
                "properties": {
                  "correcao": {
                    "type": "string",
                    "minLength": 15,
                    "maxLength": 1000
                  }
                }
              },
              "example": {
                "correcao": "Onde se lê complemento do endereço Sala 2, leia-se Sala 12."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Registrada. A carta aparece em `cartas_correcao`.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Nfe"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "aviso": {
                          "type": "object",
                          "properties": {
                            "codigo": {
                              "type": "string",
                              "example": "carta_correcao_limites"
                            },
                            "mensagem": {
                              "type": "string"
                            },
                            "sequencia": {
                              "type": "integer"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "202": {
            "description": "A resposta da SEFAZ não chegou; a Sudrel consulta e conclui sozinha (webhook `NFE_CARTA_CORRECAO_REGISTRADA`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfe"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfeNaoEncontrada"
          },
          "409": {
            "description": "`nfe_nao_aceita_carta_correcao` (só nota `autorizada`) ou `carta_correcao_em_andamento` (espere a anterior terminar).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "`evento_invalido` (texto de 15 a 1.000 caracteres), `limite_cartas_correcao` (as 20 cartas já foram usadas) ou `carta_correcao_recusada` (a SEFAZ recusou; o `cStat` vem em `codigo_oficial` e a nota inteira em `nfe`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfce": {
      "post": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "emitirNfce",
        "summary": "Emite uma NFC-e (modelo 65)",
        "description": "Responde na mesma chamada. Tributos calculados pela Sudrel a partir do produto\n(`modo: \"calcular\"`, o padrão), informados (`informado`) ou conferidos\n(`conferir`). Tudo é validado antes de reservar número: erros voltam juntos em\n422 `validacao`. Empresa sem caixa ou sem os requisitos é 412\n`empresa_nao_pronta` (veja `GET /v1/nfce/prontidao/{empresa_id}`).\n",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Obrigatória na NFC-e. Um identificador único da venda; repita o MESMO valor ao reenviar.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          },
          {
            "$ref": "#/components/parameters/PreferWait"
          },
          {
            "$ref": "#/components/parameters/SimularFalhaNfe"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NfceEntrada"
              },
              "example": {
                "empresa_id": "0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00",
                "referencia": "CUPOM-000123",
                "caixa": "LOJA1-CX02",
                "itens": [
                  {
                    "produto": "CAM-1",
                    "quantidade": 2,
                    "valor_unitario": 39.9
                  }
                ],
                "pagamentos": [
                  {
                    "forma": "dinheiro",
                    "valor": 100
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Autorizada, com o QR Code e os links do cupom.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfce"
                }
              }
            }
          },
          "202": {
            "description": "A SEFAZ não respondeu dentro da espera. Acompanhe por `GET /v1/nfce/{id}` ou pelo webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfce"
                }
              }
            }
          },
          "400": {
            "description": "`idempotency_key_obrigatoria`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "description": "`caixa_nao_encontrado` ou `empresa_nao_encontrada`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "409": {
            "description": "`referencia_duplicada` (o id da NFC-e existente vem em `nfce_id`) ou a mesma `Idempotency-Key` com outro corpo.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "412": {
            "description": "`empresa_nao_pronta`: as pendências vêm em `itens`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "`validacao` (lista em `erros`, com as regras do modelo 65 como\n`nfce_cfop_invalido` e `nfce_consumidor_obrigatorio`), `nfce_rejeitada` ou\n`nfce_denegada` (a nota completa vem em `nfce`, com `nfce_id`),\n`fora_de_cobertura` ou `conferencia_divergente`.\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      },
      "get": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "listarNfce",
        "summary": "Lista as NFC-e",
        "description": "Do ambiente da chave, mais novas primeiro, com cursor.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "referencia",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "caixa",
            "in": "query",
            "description": "Id ou identificador do caixa.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "criada_de",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "criada_ate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Nfce"
                      }
                    },
                    "proximo_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          }
        }
      }
    },
    "/v1/nfce/previas": {
      "post": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "previaNfce",
        "summary": "Valida e mostra o XML sem emitir",
        "description": "Tudo o que a emissão confere, sem reservar número e sem assinar. O XML vem sem o QR Code, que entra depois da assinatura.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NfceEntrada"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`valida`, `numero_previsto`, `chave_prevista`, `totais` (com o `troco`), `xml`, `ajustes`, `erros` e `prontidao`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          }
        }
      }
    },
    "/v1/nfce/prontidao/{empresa_id}": {
      "get": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "prontidaoNfce",
        "summary": "A empresa está pronta para emitir NFC-e?",
        "description": "A prontidão da NF-e (certificado testado na SEFAZ, inscrição estadual, endereço, regime) mais `caixa`, `nfce_uf` e `csc`. A lista de itens cresce.",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProntidaoNfe"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          }
        }
      }
    },
    "/v1/nfce/csc/{empresa_id}": {
      "get": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "situacaoCscNfce",
        "summary": "Se a empresa tem CSC cadastrado",
        "description": "Nunca devolve o CSC nem o identificador.",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cadastrado": {
                      "type": "boolean"
                    },
                    "atualizado_em": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          }
        }
      },
      "put": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "gravarCscNfce",
        "summary": "Grava (ou troca) o CSC da empresa",
        "description": "O CSC de homologação com a chave `sdr_test_`, o de produção com a `sdr_live_`.\nGuardado criptografado; os campos `id_csc` e `csc` saem mascarados do log de\nrequisições. Usado só no QR Code versão 2 (quando a UF recusa a versão 3).\n",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id_csc",
                  "csc"
                ],
                "properties": {
                  "id_csc": {
                    "type": "string",
                    "description": "Identificador do CSC (1 a 6 dígitos), como a SEFAZ mostra."
                  },
                  "csc": {
                    "type": "string",
                    "description": "O código (16 a 36 letras e números)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Gravado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cadastrado": {
                      "type": "boolean"
                    },
                    "atualizado_em": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "422": {
            "description": "`validacao` com `csc_invalido`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "removerCscNfce",
        "summary": "Remove o CSC da empresa",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Removido.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cadastrado": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          }
        }
      }
    },
    "/v1/nfce/inutilizacoes": {
      "get": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "inutilizacoesNfce",
        "summary": "Inutilizações de números de NFC-e",
        "description": "Os números de NFC-e descartadas que a Sudrel inutilizou, por faixa, como na NF-e.",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          }
        }
      }
    },
    "/v1/nfce/{id}": {
      "get": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "consultarNfce",
        "summary": "Consulta uma NFC-e",
        "description": "`{id}` aceita o id Sudrel, a sua `referencia` ou a chave de acesso.",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfceId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfce"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfceNaoEncontrada"
          }
        }
      }
    },
    "/v1/nfce/{id}/xml": {
      "get": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "baixarXmlNfce",
        "summary": "XML autorizado (nfeProc, com o QR Code)",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfceId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "XML.",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfceNaoEncontrada"
          },
          "409": {
            "description": "`nfce_sem_documento`: só nota `autorizada` ou `cancelada`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfce/{id}/danfe": {
      "get": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "cupomNfce",
        "summary": "Cupom (DANFE NFC-e) de 80 mm",
        "description": "PDF por padrão; `?formato=texto` devolve o cupom em 48 colunas para impressora térmica. Nota cancelada sai com a tarja.",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfceId"
          },
          {
            "name": "formato",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pdf",
                "texto"
              ],
              "default": "pdf"
            }
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "O cupom.",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfceNaoEncontrada"
          },
          "409": {
            "description": "`nfce_sem_documento`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfce/{id}/cancelamento": {
      "post": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "cancelarNfce",
        "summary": "Cancela uma NFC-e autorizada",
        "description": "Até `cancelavel_ate` (30 minutos da autorização na BA, RICMS/BA, art. 107-H, I).\nFila e cota próprias, separadas da emissão. Espera o resultado (`Prefer: wait`).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfceId"
          },
          {
            "$ref": "#/components/parameters/PreferWait"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "justificativa"
                ],
                "properties": {
                  "justificativa": {
                    "type": "string",
                    "minLength": 15,
                    "maxLength": 255
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cancelada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfce"
                }
              }
            }
          },
          "202": {
            "description": "A SEFAZ ainda não respondeu; acompanhe pelo webhook `NFCE_CANCELADA`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfce"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaNfceNaoEncontrada"
          },
          "409": {
            "description": "`nfe_nao_cancelavel`: só nota `autorizada` cancela.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "`cancelamento_fora_do_prazo` (com o caminho da UF em `correcao`), `justificativa_invalida` ou `cancelamento_recusado` (o `cStat` em `codigo_oficial`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfce/{id}/descarte": {
      "post": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "descartarNfce",
        "summary": "Desiste de uma NFC-e rejeitada (ou que não saiu)",
        "description": "O número vai para a inutilização automática, como na NF-e.",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfceId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "motivo": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Descartada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nfce"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "409": {
            "description": "`nfce_nao_descartavel`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfce/{id}/envio": {
      "post": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "enviarNfce",
        "summary": "Envia o cupom ao consumidor por e-mail",
        "description": "O cupom em PDF, o XML e a URL de consulta pela chave. Sem `email`, vai para o e-mail do `consumidor` da nota.",
        "parameters": [
          {
            "$ref": "#/components/parameters/NfceId"
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enviado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "enviado": {
                      "type": "boolean"
                    },
                    "nfce_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "409": {
            "description": "`nfce_nao_enviavel` (só autorizada) ou `nfce_sem_documento`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "`email_invalido`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/caixas": {
      "get": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "listarCaixas",
        "summary": "Lista os caixas de NFC-e",
        "description": "Do ambiente da chave (o sandbox tem os caixas dele).",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CaixaNfce"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          }
        }
      },
      "post": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "criarCaixa",
        "summary": "Cadastra um caixa",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "empresa_id",
                  "identificador",
                  "serie"
                ],
                "properties": {
                  "empresa_id": {
                    "type": "string"
                  },
                  "identificador": {
                    "type": "string",
                    "maxLength": 40,
                    "description": "Letras, números, ponto, hífen e sublinhado. Único na empresa."
                  },
                  "serie": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 889,
                    "description": "Única na empresa; não muda depois da primeira NFC-e do caixa."
                  },
                  "descricao": {
                    "type": "string",
                    "maxLength": 120
                  }
                }
              },
              "example": {
                "empresa_id": "0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00",
                "identificador": "LOJA1-CX02",
                "serie": 2,
                "descricao": "Caixa da frente"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaixaNfce"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "422": {
            "description": "`serie_invalida`, `caixa_serie_duplicada` ou `caixa_identificador_duplicado`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/caixas/{id}": {
      "get": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "consultarCaixa",
        "summary": "Consulta um caixa",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id Sudrel ou identificador do caixa.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaixaNfce"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "description": "`caixa_nao_encontrado`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Emissão de NFC-e"
        ],
        "operationId": "alterarCaixa",
        "summary": "Altera um caixa",
        "description": "Identificador, descrição, situação (`ativo`/`inativo`) e, antes da primeira NFC-e, a série.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "identificador": {
                    "type": "string"
                  },
                  "descricao": {
                    "type": "string"
                  },
                  "serie": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 889
                  },
                  "situacao": {
                    "type": "string",
                    "enum": [
                      "ativo",
                      "inativo"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaixaNfce"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "422": {
            "description": "`caixa_serie_em_uso` (o caixa já emitiu), `caixa_serie_duplicada` ou `caixa_identificador_duplicado`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/produtos": {
      "post": {
        "tags": [
          "Produtos e motor fiscal"
        ],
        "operationId": "criarProdutoNfe",
        "summary": "Cadastra um produto",
        "description": "NCM, CEST e GTIN conferidos nas tabelas oficiais antes de gravar, e o GTIN\ntambém na SEFAZ. A chave de sandbox grava num cadastro só dela.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProdutoEntrada"
              },
              "example": {
                "empresa_id": "0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00",
                "codigo": "SKU-123",
                "descricao": "Camiseta de algodão",
                "ncm": "61091000",
                "unidade": "UN",
                "origem": "0",
                "perfil_fiscal": {
                  "icms": "tributado",
                  "pis_cofins": "tributado",
                  "ibs_cbs": {
                    "cst": "000",
                    "classificacao_tributaria": "000001"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cadastrado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Produto"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "409": {
            "description": "`produto_duplicado`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "`validacao`, com `ncm_inexistente`, `cest_incompativel_ncm`, `gtin_digito_invalido`, `gtin_ncm_divergente` e outros em `erros`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Produtos e motor fiscal"
        ],
        "operationId": "listarProdutosNfe",
        "summary": "Lista os produtos",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ncm",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Produto"
                      }
                    },
                    "proximo_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          }
        }
      }
    },
    "/v1/produtos/{codigo}": {
      "get": {
        "tags": [
          "Produtos e motor fiscal"
        ],
        "operationId": "obterProdutoNfe",
        "summary": "Consulta um produto pelo código",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "empresa_id",
            "in": "query",
            "description": "Obrigatório quando a conta tem mais de uma empresa e a chave não é restrita.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Produto"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "description": "`produto_nao_encontrado`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Produtos e motor fiscal"
        ],
        "operationId": "alterarProdutoNfe",
        "summary": "Altera um produto",
        "description": "Só os campos enviados. Mudar campo fiscal (NCM, CEST, origem, EX da TIPI, produção própria ou perfil) apaga a aprovação do perfil. `ativo` desativa o produto.",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProdutoEntrada"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Alterado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Produto"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "422": {
            "description": "`validacao`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/produtos/{codigo}/aprovacao-perfil": {
      "post": {
        "tags": [
          "Produtos e motor fiscal"
        ],
        "operationId": "aprovarPerfilProdutoNfe",
        "summary": "Aprova o perfil fiscal do produto",
        "description": "Grava quem aprovou (nome e e-mail da pessoa da empresa ou do escritório), quando e com qual chave. Sem aprovação, o produto não entra no modo calcular.",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Aprovacao"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Aprovado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Produto"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "422": {
            "description": "`aprovador_obrigatorio` ou `perfil_incompleto`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/produtos/{codigo}/vinculos-entrada": {
      "get": {
        "tags": [
          "Produtos e motor fiscal"
        ],
        "operationId": "listarVinculosEntradaProdutoNfe",
        "summary": "Lista os vínculos do produto com as compras",
        "description": "Os vínculos dizem de quais itens de nota de compra saem os valores de ICMS-ST\nretido anteriormente na revenda (CST 60 / CSOSN 500). `st_retido_previsto` mostra\no que sairia agora para `quantidade` unidades: das últimas aquisições,\nproporcional à quantidade (Convênio ICMS 142/18, cláusula décima quinta, §3º).\n",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantidade",
            "in": "query",
            "schema": {
              "type": "number",
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/VinculoEntradaProduto"
                      }
                    },
                    "st_retido_previsto": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "quantidade": {
                          "type": "number"
                        },
                        "base_calculo": {
                          "type": "number"
                        },
                        "aliquota": {
                          "type": "number"
                        },
                        "valor_substituto": {
                          "type": "number"
                        },
                        "valor": {
                          "type": "number"
                        },
                        "fonte": {
                          "type": "string"
                        }
                      }
                    },
                    "regra": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "description": "`produto_nao_encontrado`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Produtos e motor fiscal"
        ],
        "operationId": "criarVinculoEntradaProdutoNfe",
        "summary": "Vincula o produto às compras",
        "description": "Três critérios: `gtin` (o GTIN do item na nota de compra), `codigo_fornecedor`\n(CNPJ do fornecedor e o código do produto na nota dele) ou `manual` (o id de um\nitem de nota recebida). A chave de sandbox grava no cadastro dela, lendo as\nnotas de compra que a empresa já tem.\n",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "criterio"
                ],
                "properties": {
                  "criterio": {
                    "type": "string",
                    "enum": [
                      "gtin",
                      "codigo_fornecedor",
                      "manual"
                    ]
                  },
                  "gtin": {
                    "type": "string"
                  },
                  "cnpj_fornecedor": {
                    "type": "string"
                  },
                  "codigo_fornecedor": {
                    "type": "string"
                  },
                  "item_nota_fiscal_id": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "criterio": "codigo_fornecedor",
                "cnpj_fornecedor": "11444777000161",
                "codigo_fornecedor": "FORN-1"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Vinculado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VinculoEntradaProduto"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "422": {
            "description": "`validacao`, com `vinculo_invalido` ou `item_nao_encontrado` em `erros`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/produtos/{codigo}/vinculos-entrada/{id}": {
      "delete": {
        "tags": [
          "Produtos e motor fiscal"
        ],
        "operationId": "removerVinculoEntradaProdutoNfe",
        "summary": "Remove um vínculo",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "empresa_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Removido."
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "description": "`produto_nao_encontrado` ou `vinculo_nao_encontrado`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfe/perfil-fiscal/{empresa_id}": {
      "get": {
        "tags": [
          "Produtos e motor fiscal"
        ],
        "operationId": "obterPerfilFiscalNfe",
        "summary": "Perfil fiscal da empresa",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PerfilFiscalNfe"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          }
        }
      },
      "put": {
        "tags": [
          "Produtos e motor fiscal"
        ],
        "operationId": "gravarPerfilFiscalNfe",
        "summary": "Grava o perfil fiscal da empresa",
        "description": "Só os campos enviados. Mudar o regime de PIS/COFINS, o IPI, a isenção por\nfaixa ou a recusa de divergências apaga a aprovação; a alíquota de crédito do\nmês do Simples (`credito_simples`) não apaga (é informação do mês), mas vai\npara a auditoria. Mudar `exclui_icms_base_pis_cofins` ou `termo_acordo` também\napaga a aprovação. O CRT vem do regime tributário do cadastro da empresa. A\nchave de sandbox grava num perfil só dela.\n",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PerfilFiscalNfe"
              },
              "example": {
                "regime_pis_cofins": "nao_cumulativo",
                "contribuinte_ipi": false,
                "credito_simples": {
                  "competencia": "2026-10",
                  "aliquota": 2.56
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Gravado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PerfilFiscalNfe"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "422": {
            "description": "`validacao`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/nfe/perfil-fiscal/{empresa_id}/aprovacao": {
      "post": {
        "tags": [
          "Produtos e motor fiscal"
        ],
        "operationId": "aprovarPerfilFiscalNfe",
        "summary": "Aprova o perfil fiscal da empresa",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Aprovacao"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Aprovado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PerfilFiscalNfe"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "422": {
            "description": "`aprovador_obrigatorio` ou `perfil_inexistente`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/v1/lotes": {
      "post": {
        "tags": [
          "Emissão em lote"
        ],
        "operationId": "criarLote",
        "summary": "Cria um lote de emissão",
        "description": "Até **5.000 notas** num lote (com a chave de sandbox, **100**), por JSON\nou pela planilha do painel. O lote passa pela mesma validação, pela mesma\nnormalização e pela mesma fila da planilha do painel. Sempre **202**: o\nlote é assíncrono. Acompanhe por `GET /v1/lotes/{id}` ou pelo webhook\n`LOTE_EMISSAO_CONCLUIDO`.\n\n**Duas formas de entrada, mesma rota:**\n\n- `application/json`: `{ \"empresa_id\", \"modelo\"?, \"ao_validar\"?, \"itens\": [...] }`.\n  Cada item é exatamente o corpo de `POST /v1/nfse` (mesmos campos, mesma\n  validação), com `referencia` opcional por item.\n- `multipart/form-data`: campo `planilha` (.xlsx ou .csv separado por\n  vírgula, no template oficial, qualquer dos três layouts) e os campos\n  `empresa_id`, `modelo` e `ao_validar` no formulário.\n\n**`ao_validar`:**\n\n- `emitir_validas` (padrão): as linhas válidas entram na fila assim que\n  o lote é validado; as inválidas ficam com erro no resultado, e você\n  corrige com `POST /v1/lotes/{id}/reprocessamento`.\n- `aguardar`: o lote para depois da validação. Confira o resultado e\n  chame `POST /v1/lotes/{id}/emissao`. Serve para quem quer tudo ou nada.\n\n**Reenvio seguro com `referencia`.** Mande sempre uma `referencia` por\nitem (o seu número de pedido, por exemplo). Se o mesmo lote for enviado\nde novo (um timeout, um retry automático), a linha cuja referência já\nvirou nota **não vira outra nota**: aparece como `ja_existente`, com o\n`nfse_id` da nota que já existe. Se o conteúdo da linha mudou,\n`divergente: true` avisa, e mesmo assim nenhuma nota nova é criada.\nReferência repetida **dentro do mesmo lote** é erro nas linhas\nenvolvidas (`referencia_duplicada_no_lote`), e nenhuma delas vira nota.\n\n> ⚠️ **Linha sem `referencia` não tem essa proteção.** Reenviar um lote\n> sem referências emite as notas de novo. Em lote, mande sempre\n> `referencia`.\n\nUse também `Idempotency-Key`: a mesma chave com o mesmo corpo devolve o\nmesmo lote; com corpo diferente, 409 `idempotencia_conflito`. Na\nplanilha, o \"corpo\" é o arquivo (hash) mais os campos do formulário.\n\nA prontidão da empresa é avaliada uma vez, antes de criar o lote:\n`bloqueio` devolve **412** `empresa_nao_pronta`, como no\n`POST /v1/nfse`, e nada é criado.\n\n**Limite de requisições:** um `POST /v1/lotes` conta como **uma**\nchamada, qualquer que seja o número de itens.\n\nItens de lote entram na fila de emissão atrás das notas avulsas\n(`POST /v1/nfse`): um lote grande não atrasa a nota de outro cliente.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "itens"
                ],
                "properties": {
                  "tipo": {
                    "type": "string",
                    "enum": [
                      "nfse",
                      "nfe"
                    ],
                    "default": "nfse",
                    "description": "`nfe`: cada item é o corpo de `POST /v1/nfe` (veja NF-e pela planilha e em lote). Sem `tipo`, o lote é de NFS-e."
                  },
                  "empresa_id": {
                    "type": "string"
                  },
                  "modelo": {
                    "type": "string",
                    "description": "Nome ou id de um modelo de emissão; vale pra todos os itens que não pedirem outro. Só no lote de NFS-e."
                  },
                  "ao_validar": {
                    "type": "string",
                    "enum": [
                      "emitir_validas",
                      "aguardar"
                    ],
                    "default": "emitir_validas"
                  },
                  "itens": {
                    "type": "array",
                    "maxItems": 5000,
                    "items": {
                      "$ref": "#/components/schemas/NfseEntrada"
                    }
                  }
                }
              },
              "example": {
                "empresa_id": "0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00",
                "itens": [
                  {
                    "referencia": "PED-1001",
                    "tomador": {
                      "documento": "11222333000181"
                    },
                    "valor": "1500.00",
                    "servico": {
                      "descricao": "Consultoria, outubro/2026"
                    }
                  },
                  {
                    "referencia": "PED-1002",
                    "tomador": {
                      "documento": "11222333000181"
                    },
                    "valor": "320.00",
                    "servico": {
                      "descricao": "Suporte, outubro/2026"
                    }
                  }
                ]
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "planilha"
                ],
                "properties": {
                  "planilha": {
                    "type": "string",
                    "format": "binary",
                    "description": ".xlsx ou .csv no template oficial, até 20 MB."
                  },
                  "tipo": {
                    "type": "string",
                    "enum": [
                      "nfse",
                      "nfe"
                    ],
                    "default": "nfse",
                    "description": "`nfe`: a planilha de notas de NF-e (Básica ou Completa)."
                  },
                  "empresa_id": {
                    "type": "string"
                  },
                  "modelo": {
                    "type": "string"
                  },
                  "ao_validar": {
                    "type": "string",
                    "enum": [
                      "emitir_validas",
                      "aguardar"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Lote criado. Validação e emissão seguem em segundo plano.",
            "headers": {
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "`/v1/lotes/{id}`"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Lote"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/ProblemaAcessoNegado"
          },
          "404": {
            "description": "`empresa_nao_encontrada`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "409": {
            "description": "`idempotencia_conflito` (mesma `Idempotency-Key` com outro corpo) ou `conflito` (a mesma chave ainda está em processamento).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "412": {
            "description": "`empresa_nao_pronta`, com a prontidão em `itens`. Nada foi criado.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "`validacao`: o LOTE tem erro (sem itens, acima do teto, `ao_validar`\ninválido, modelo inexistente, planilha ilegível). Nada foi criado.\nErros de um ITEM não chegam aqui: aparecem no resultado da linha.\nTambém `planilha_obrigatoria` (multipart sem o arquivo) e\n`simulacao_so_no_sandbox` / `simulacao_invalida` (campo `simular`).\nPlanilha acima de 20 MB é recusada com 413.\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      },
      "get": {
        "tags": [
          "Emissão em lote"
        ],
        "operationId": "listarLotes",
        "summary": "Lista os lotes",
        "description": "Mais recente primeiro, por cursor. Lista os lotes criados pela API e\npela planilha do painel (a chave de sandbox vê só os de sandbox). Com\n`status`, a página pode vir menor que `limite`: continue até\n`proximo_cursor` vir nulo. A última página pode vir vazia.\n",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "validando",
                "aguardando_emissao",
                "processando",
                "concluido",
                "erro"
              ]
            }
          },
          {
            "name": "criado_de",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Data ISO 8601."
          },
          {
            "name": "criado_ate",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Data ISO 8601."
          },
          {
            "name": "limite",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "1 a 100, padrão 20. Fora da faixa é 400 `parametro_invalido`."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Lote"
                      }
                    },
                    "proximo_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/lotes/{id}": {
      "get": {
        "tags": [
          "Emissão em lote"
        ],
        "operationId": "consultarLote",
        "summary": "Consulta um lote",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Lote"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "description": "`lote_nao_encontrado`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/lotes/{id}/itens": {
      "get": {
        "tags": [
          "Emissão em lote"
        ],
        "operationId": "itensDoLote",
        "summary": "Resultado por linha",
        "description": "Um item por linha (número da linha na planilha, cabeçalho = 1; ou a\nposição no array JSON, começando em 1), por cursor. Os erros vêm no\nmesmo formato do 422 de `POST /v1/nfse`. Os `ajustes` aparecem nas notas\njá mandadas emitir.\n",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/StatusItemLote"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "1 a 500, padrão 100."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "`proximo_cursor` da página anterior."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ItemLote"
                      }
                    },
                    "proximo_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaLoteNaoEncontrado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/lotes/{id}/relatorio": {
      "get": {
        "tags": [
          "Emissão em lote"
        ],
        "operationId": "relatorioDoLote",
        "summary": "Relatório em planilha",
        "description": "A planilha que você enviou, com colunas acrescentadas no fim: status,\nnúmero da NFS-e, chave de acesso, erro, correção e ajustes. Lote em JSON\nvira uma planilha gerada dos itens, com as mesmas colunas.\n",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "XLSX.",
            "content": {
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaLoteNaoEncontrado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/lotes/{id}/emissao": {
      "post": {
        "tags": [
          "Emissão em lote"
        ],
        "operationId": "emitirLote",
        "summary": "Manda emitir um lote que aguardava",
        "description": "Só para lote criado com `ao_validar: \"aguardar\"`, depois da validação,\numa vez. `\"todas\"` emite todas as linhas válidas; uma lista de números\nde linha emite só essas, e as outras válidas viram `descartada`. As\nlinhas com erro ficam para o reprocessamento.\n",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "itens": {
                    "oneOf": [
                      {
                        "type": "string",
                        "enum": [
                          "todas"
                        ]
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "integer"
                        }
                      }
                    ]
                  }
                }
              },
              "example": {
                "itens": [
                  2,
                  3,
                  7
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Emissão disparada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Lote"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaLoteNaoEncontrado"
          },
          "409": {
            "description": "`lote_ja_emitido`, `lote_validando` ou `lote_sem_emissao_manual`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "412": {
            "description": "`empresa_nao_pronta`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "`validacao` (`itens_invalidos`): a lista tem número que não é linha válida do lote.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/lotes/{id}/reprocessamento": {
      "post": {
        "tags": [
          "Emissão em lote"
        ],
        "operationId": "reprocessarLote",
        "summary": "Corrige linhas e emite de novo",
        "description": "Cada item corrige campos de uma linha (os mesmos campos de\n`POST /v1/nfse`) e manda emitir de novo. Só aceita linha com erro de\nvalidação, `rejeitada`, ou `falha_transmissao` com\n`falha.dps_enviada = \"nao\"`. Com `\"desconhecido\"`, a DPS pode ter virado\nnota e reemitir duplicaria: confira no Emissor Nacional antes\n(`dps_possivelmente_enviada`). Linha autorizada, cancelada ou em\ntransmissão nunca é tocada (`linha_nao_reprocessavel`). A referência, a\nempresa e o modelo da linha não mudam.\n\nReprocessar é decisão sua de transmitir agora: vale como confirmação na\ntrava de competência.\n",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "itens"
                ],
                "properties": {
                  "itens": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "linha"
                      ],
                      "properties": {
                        "linha": {
                          "type": "integer"
                        },
                        "campos": {
                          "$ref": "#/components/schemas/NfseEntrada"
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "itens": [
                  {
                    "linha": 12,
                    "campos": {
                      "valor": "150.00"
                    }
                  },
                  {
                    "linha": 40
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado por linha. Linha aceita vem no formato de `itens`; linha\nrecusada vem com `recusado: true` e o motivo em `erros`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "oneOf": [
                          {
                            "$ref": "#/components/schemas/ItemLote"
                          },
                          {
                            "type": "object",
                            "properties": {
                              "linha": {
                                "type": "integer"
                              },
                              "recusado": {
                                "type": "boolean"
                              },
                              "erros": {
                                "type": "array",
                                "items": {
                                  "$ref": "#/components/schemas/ErroCampo"
                                }
                              }
                            }
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "$ref": "#/components/responses/ProblemaLoteNaoEncontrado"
          },
          "422": {
            "description": "`validacao`: `itens_obrigatorios` ou `lote_acima_do_limite` (mais de 5.000).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/webhooks": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "criarWebhook",
        "summary": "Cria um webhook",
        "description": "Aceita `Idempotency-Key`. O `segredo` vem SÓ nesta resposta. O\nambiente é o da chave (`sdr_test_` cria webhook de sandbox). Chave\nrestrita a uma empresa não administra webhooks (403 `chave_restrita`).\n",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEntrada"
              },
              "example": {
                "url": "https://erp.exemplo.com.br/webhooks/sudrel",
                "eventos": [
                  "NFSE_AUTORIZADA",
                  "NFSE_REJEITADA",
                  "LOTE_EMISSAO_CONCLUIDO"
                ],
                "cabecalhos": [
                  {
                    "nome": "Authorization",
                    "valor": "Bearer seu-token"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criado. Guarde o `segredo`.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Webhook"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "segredo": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "422": {
            "description": "`validacao`, com os erros em `erros` (`url_invalida`, `url_nao_permitida`, `evento_invalido`, `cabecalho_invalido`)."
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      },
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "listarWebhooks",
        "summary": "Lista os webhooks do ambiente da chave",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhooks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "obterWebhook",
        "summary": "Um webhook",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      },
      "patch": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "alterarWebhook",
        "summary": "Altera eventos, endereço, ativo ou cabeçalhos",
        "description": "`cabecalhos` substitui a lista inteira; `[]` apaga.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEntrada"
              },
              "example": {
                "ativo": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "removerWebhook",
        "summary": "Remove o webhook",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Removido."
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/webhooks/{id}/rotacao-segredo": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "rotacionarSegredoWebhook",
        "summary": "Troca o segredo, com 24 horas de convivência",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "O segredo novo. Até `segredo_anterior_valido_ate` as entregas levam as duas assinaturas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "segredo": {
                      "type": "string"
                    },
                    "segredo_anterior_valido_ate": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/webhooks/{id}/teste": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "testarWebhook",
        "summary": "Manda um evento `webhook.teste` agora",
        "description": "Nada fica gravado; os ids de evento e de entrega são novos a cada teste.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resultado da tentativa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sucesso": {
                      "type": "boolean"
                    },
                    "status_http": {
                      "type": "integer",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/webhooks/{id}/entregas": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "listarEntregasWebhook",
        "summary": "Entregas do webhook, das mais novas para as mais antigas",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "sucesso",
                "pendente",
                "falhou"
              ]
            }
          },
          {
            "name": "evento",
            "in": "query",
            "description": "Tipo do evento.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "desde",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "ate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "entregas": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EntregaWebhook"
                      }
                    },
                    "proximo_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/webhooks/{id}/reenvio": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "reenviarWebhook",
        "summary": "Reenvia eventos (um, um período ou um lote)",
        "description": "Exatamente um de `evento_id`, `desde` + `ate`, ou `lote_id`. Só eventos\ndo ambiente do webhook e dos tipos que ele assina. Cada evento vira\numa entrega nova com o MESMO `X-Sudrel-Event-Id`, enviada em segundos\nse o webhook estiver ativo (com `ativo: false`, as entregas esperam o\nwebhook ser religado). Até 500 por chamada.\n",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "evento_id": {
                    "type": "string"
                  },
                  "desde": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "ate": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "lote_id": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "desde": "2026-10-01T00:00:00Z",
                "ate": "2026-10-02T00:00:00Z"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Entregas criadas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total_encontrado": {
                      "type": "integer"
                    },
                    "reenviados": {
                      "type": "integer"
                    },
                    "limite_por_chamada": {
                      "type": "integer"
                    },
                    "sem_corpo": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Eventos cujo recurso não existe mais."
                    },
                    "entregas": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "continuar_desde": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "404": {
            "description": "`evento_nao_encontrado` ou `lote_nao_encontrado`."
          },
          "422": {
            "description": "`reenvio_invalido` ou `evento_nao_assinado`."
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    },
    "/v1/eventos": {
      "get": {
        "tags": [
          "Eventos"
        ],
        "operationId": "listarEventos",
        "summary": "Log de eventos da conta, por cursor",
        "description": "Chave de sandbox lê só eventos de sandbox, a de produção só os de\nprodução; chave restrita a uma empresa, só os dessa empresa.\n",
        "parameters": [
          {
            "name": "apos",
            "in": "query",
            "description": "O `proximo_cursor` da página anterior. Sem ele, começa do mais antigo disponível.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tipos",
            "in": "query",
            "description": "Tipos separados por vírgula.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "eventos": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EventoConta"
                      }
                    },
                    "proximo_cursor": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/ProblemaNaoAutenticado"
          },
          "410": {
            "description": "`cursor_vencido`: mais velho que a retenção de 90 dias. `cursor_mais_antigo` diz de onde continuar."
          },
          "429": {
            "$ref": "#/components/responses/ProblemaLimite"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "chaveApi": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sdr_live_... (produção) ou sdr_test_... (teste de emissão)",
        "description": "Chave de API gerada em Painel → Chaves de API."
      }
    },
    "parameters": {
      "SimularFalha": {
        "name": "X-Sudrel-Simular",
        "in": "header",
        "required": false,
        "description": "Simulador de falhas, só com a chave `sdr_test_` (com a de produção é\n422 `simulacao_so_no_sandbox`). Um cenário da seção **Simulador de\nfalhas**, por exemplo `timeout_depois_autorizada` ou `rejeicao:E0240`.\nCenário desconhecido é 422 `simulacao_invalida`.\n",
        "schema": {
          "type": "string"
        }
      },
      "SimularFalhaNfe": {
        "name": "X-Sudrel-Simular",
        "in": "header",
        "required": false,
        "description": "Simulador de falhas da NF-e, só com a chave `sdr_test_`. Um cenário da\nseção **Simulador de falhas** (parte NF-e), por exemplo `denegada` ou\n`rejeicao:778`. Cenário desconhecido é 422 `simulacao_invalida`.\n",
        "schema": {
          "type": "string"
        }
      },
      "NfceId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Id Sudrel da NFC-e, a sua `referencia` ou a chave de acesso (44 dígitos).",
        "schema": {
          "type": "string"
        }
      },
      "NfeId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Id Sudrel da NF-e, a sua `referencia` ou a chave de acesso (44 dígitos).",
        "schema": {
          "type": "string"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Identificador único da SUA tentativa de emissão (ex.: um UUID gerado\npelo seu sistema). Mesma chave e mesmo corpo: mesma resposta, sem nota\nnova, por 30 dias. Mesma chave e corpo diferente: 409 nas primeiras 24\nhoras; depois disso, a chave vale como nova.\n",
        "schema": {
          "type": "string"
        }
      },
      "PreferWait": {
        "name": "Prefer",
        "in": "header",
        "required": false,
        "description": "`wait=N`: quantos segundos a chamada acompanha a nota antes de responder 202. Padrão 10, máximo 30; `wait=0` responde na hora.",
        "schema": {
          "type": "string",
          "example": "wait=15"
        }
      },
      "NfseId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Id Sudrel da nota, a sua `referencia` ou a chave de acesso.",
        "schema": {
          "type": "string"
        }
      },
      "EmpresaId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Id da empresa (o mesmo devolvido em `GET /companies`).",
        "schema": {
          "type": "string"
        }
      }
    },
    "examples": {
      "NfeEntradaVenda": {
        "summary": "Venda no modo informado (tributos prontos), destinatário só pelo CNPJ",
        "value": {
          "empresa_id": "0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00",
          "referencia": "PED-10293",
          "natureza_operacao": "Venda de mercadoria",
          "presenca": "internet",
          "consumidor_final": true,
          "destinatario": {
            "documento": "13937073000156"
          },
          "itens": [
            {
              "codigo": "SKU-123",
              "descricao": "Camiseta de algodão",
              "ncm": "61091000",
              "cfop": "5102",
              "origem": "0",
              "unidade": "UN",
              "quantidade": 2,
              "valor_unitario": 89.9,
              "icms": {
                "csosn": "102"
              },
              "pis": {
                "cst": "99",
                "base_calculo": 0,
                "aliquota": 0,
                "valor": 0
              },
              "cofins": {
                "cst": "99",
                "base_calculo": 0,
                "aliquota": 0,
                "valor": 0
              }
            }
          ],
          "pagamentos": [
            {
              "forma": "pix",
              "valor": 179.8
            }
          ]
        }
      },
      "NfeEntradaCalcular": {
        "summary": "Venda no modo calcular, destinatário só pelo CNPJ",
        "description": "O motor resolve CFOP, natureza e tributos pelo produto cadastrado; nome,\nendereço e inscrição estadual do destinatário vêm da Receita e da SEFAZ.\nO CNPJ precisa existir na Receita (este é o da SEFAZ-BA).\n",
        "value": {
          "empresa_id": "0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00",
          "referencia": "PED-10294",
          "modo": "calcular",
          "presenca": "internet",
          "destinatario": {
            "documento": "13937073000156"
          },
          "itens": [
            {
              "produto": "SKU-123",
              "quantidade": 2,
              "valor_unitario": 89.9
            }
          ],
          "pagamentos": [
            {
              "forma": "pix"
            }
          ]
        }
      },
      "NfeAutorizada": {
        "summary": "NF-e autorizada (sandbox)",
        "value": {
          "id": "5c1e9a70-2b3d-4e5f-8a9b-0c1d2e3f4a5b",
          "referencia": "PED-10293",
          "status": "autorizada",
          "empresa_id": "0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00",
          "ambiente": "sandbox",
          "simulacao": null,
          "modo": "informado",
          "modelo": 55,
          "serie": 1,
          "numero": 42,
          "chave_acesso": "29261011444777000161550010000000421123456780",
          "chaves_anteriores": [],
          "chave_referenciada": null,
          "protocolo": "129260000000001",
          "emitida_em": "2026-10-16T13:02:11.000Z",
          "autorizada_em": "2026-10-16T13:02:13.000Z",
          "valor_total": "179.80",
          "sefaz": {
            "cstat": "100",
            "motivo": "Autorizado o uso da NF-e"
          },
          "rejeicao": null,
          "denegacao": null,
          "confirmacao": null,
          "descarte": null,
          "cancelamento": null,
          "cartas_correcao": [],
          "ajustes": [
            {
              "campo": "/modo",
              "acao": "preenchido",
              "motivo": "Nesta versão os tributos vêm prontos do seu ERP.",
              "regra": "nfe_modo_informado"
            },
            {
              "campo": "/transporte/modalidade",
              "acao": "preenchido",
              "motivo": "Sem transporte informado: \"sem frete\" (modFrete 9).",
              "regra": "nfe_transporte_sem_frete"
            }
          ],
          "eventos": [
            {
              "tipo": "criada",
              "em": "2026-10-16T13:02:10.000Z",
              "detalhe": {
                "origem": "api"
              }
            },
            {
              "tipo": "resultado_sefaz",
              "em": "2026-10-16T13:02:13.000Z",
              "detalhe": {
                "cStat": "100"
              }
            }
          ],
          "regras_versao": "2026-10-16.1+nfe-montagem-2026-10-16.1",
          "criada_em": "2026-10-16T13:02:10.000Z",
          "atualizada_em": "2026-10-16T13:02:13.000Z",
          "links": {
            "self": "/v1/nfe/5c1e9a70-2b3d-4e5f-8a9b-0c1d2e3f4a5b",
            "xml": "/v1/nfe/5c1e9a70-2b3d-4e5f-8a9b-0c1d2e3f4a5b/xml",
            "danfe": "/v1/nfe/5c1e9a70-2b3d-4e5f-8a9b-0c1d2e3f4a5b/danfe"
          }
        }
      },
      "NfeRejeitadaProblema": {
        "summary": "Rejeitada pela SEFAZ",
        "value": {
          "type": "https://sudrel.com.br/docs/erros/nfe_rejeitada",
          "codigo": "nfe_rejeitada",
          "codigo_oficial": "778",
          "campo": "/itens/0/ncm",
          "mensagem": "Rejeição: Informado NCM inexistente",
          "correcao": "Confira o NCM do item na tabela oficial (TIPI) e corrija por POST /v1/nfe/{id}/correcao.",
          "retentavel": false,
          "nfe_id": "5c1e9a70-2b3d-4e5f-8a9b-0c1d2e3f4a5b"
        }
      },
      "NfseAutorizada": {
        "summary": "Nota autorizada",
        "value": {
          "id": "9d2f0c1e-3a4b-4c5d-8e9f-0a1b2c3d4e5f",
          "referencia": "PED-1001",
          "status": "autorizada",
          "empresa_id": "0b7e6a52-3c1d-4f8e-9a20-5d4c3b2a1f00",
          "ambiente": "producao",
          "origem": "api",
          "numero": "1843",
          "chave_acesso": "29274082260670420000107000000000184326091234567890",
          "dps": {
            "serie": "1",
            "numero": "57"
          },
          "valor": "1500.00",
          "tomador": {
            "tipo": "cnpj",
            "documento": "11222333000181",
            "razao_social": "Cliente Exemplo LTDA",
            "email": null,
            "endereco": {
              "logradouro": "Avenida Sete de Setembro",
              "numero": "100",
              "complemento": null,
              "bairro": "Centro",
              "cep": "40060000",
              "municipio_ibge": "2927408"
            }
          },
          "servico": {
            "codigo_nacional": "010701",
            "descricao": "Consultoria em sistemas, setembro/2026",
            "competencia": "2026-09"
          },
          "retencoes": {
            "iss": false,
            "pis": null,
            "cofins": null,
            "csll": null,
            "irrf": null,
            "inss": null
          },
          "apuracao_propria": {
            "pis": null,
            "cofins": null
          },
          "iss": {
            "aliquota": null
          },
          "rejeicao": null,
          "falha": null,
          "cancelamento": null,
          "recuperada_em": null,
          "ajustes": [
            {
              "campo": "/servico/codigo_nacional",
              "acao": "preenchido",
              "motivo": "Não informado: usado o código de tributação nacional configurado na empresa.",
              "regra": "padrao_empresa.codigoServico"
            },
            {
              "campo": "/tomador/razao_social",
              "acao": "preenchido",
              "motivo": "Razão social consultada pelo CNPJ do tomador.",
              "regra": "consulta_cnpj.razao_social"
            },
            {
              "campo": "/servico/competencia",
              "acao": "preenchido",
              "motivo": "Competência não informada: usado o mês atual.",
              "regra": "competencia.mes_atual"
            },
            {
              "campo": "/prestador/inscricao_municipal",
              "acao": "omitido",
              "motivo": "O município não aceita a inscrição municipal do prestador nesta DPS (E0120). A nota foi reenviada sem ela.",
              "regra": "correcao.E0120"
            }
          ],
          "eventos": [
            {
              "tipo": "criada",
              "em": "2026-09-30T14:02:11.120Z",
              "detalhe": {
                "origem": "api"
              }
            },
            {
              "tipo": "envio",
              "em": "2026-09-30T14:02:11.840Z",
              "detalhe": {
                "dps": {
                  "serie": "1",
                  "numero": "57"
                },
                "resultado": "rejeitada",
                "motivo": "E0120: IM não deve ser informado."
              }
            },
            {
              "tipo": "correcao_automatica",
              "em": "2026-09-30T14:02:11.850Z",
              "detalhe": {
                "regra": "correcao.E0120",
                "codigo_rejeicao": "E0120"
              }
            },
            {
              "tipo": "envio",
              "em": "2026-09-30T14:02:12.510Z",
              "detalhe": {
                "dps": {
                  "serie": "1",
                  "numero": "57"
                },
                "resultado": "autorizada"
              }
            }
          ],
          "regras_versao": "2026-09-30.1+2026-10-02.1",
          "criada_em": "2026-09-30T14:02:11.100Z",
          "atualizada_em": "2026-09-30T14:02:12.600Z",
          "links": {
            "self": "/v1/nfse/9d2f0c1e-3a4b-4c5d-8e9f-0a1b2c3d4e5f",
            "xml": "/v1/nfse/9d2f0c1e-3a4b-4c5d-8e9f-0a1b2c3d4e5f/xml",
            "pdf": "/v1/nfse/9d2f0c1e-3a4b-4c5d-8e9f-0a1b2c3d4e5f/pdf"
          }
        }
      }
    },
    "responses": {
      "LimiteRequisicoes": {
        "description": "120 requisições por minuto por chave excedidas (janela fixa de 60 s,\nalinhada ao relógio). Sem cabeçalho `Retry-After`: espere a virada do\nminuto. Nas rotas de conta, empresas e documentos o corpo é este; nas\nde emissão, lote, webhooks e eventos é problem+json\n`limite_de_requisicoes`.\n",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string"
                },
                "code": {
                  "type": "string",
                  "enum": [
                    "RATE_LIMITED"
                  ]
                }
              }
            },
            "example": {
              "message": "Limite de requisições excedido. Tente novamente em instantes.",
              "code": "RATE_LIMITED"
            }
          }
        }
      },
      "ProblemaLimite": {
        "description": "`limite_de_requisicoes` (`retentavel: true`): 120 requisições por minuto\npor chave, janela fixa de 60 s. Sem `Retry-After`: espere a virada do\nminuto e repita a MESMA requisição (com a mesma `Idempotency-Key`).\n",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problema"
            },
            "example": {
              "type": "https://sudrel.com.br/docs/erros/limite_de_requisicoes",
              "codigo": "limite_de_requisicoes",
              "codigo_oficial": null,
              "campo": null,
              "mensagem": "Limite de requisições excedido. Tente novamente em instantes.",
              "correcao": null,
              "retentavel": true,
              "requisicao_id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e"
            }
          }
        }
      },
      "ProblemaNaoAutenticado": {
        "description": "`nao_autenticado`: chave de API ausente, inválida ou revogada.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problema"
            },
            "example": {
              "type": "https://sudrel.com.br/docs/erros/nao_autenticado",
              "codigo": "nao_autenticado",
              "codigo_oficial": null,
              "campo": null,
              "mensagem": "Chave de API inválida ou revogada.",
              "correcao": null,
              "retentavel": false,
              "requisicao_id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e"
            }
          }
        }
      },
      "ProblemaAcessoNegado": {
        "description": "`acesso_negado`: a chave é restrita a outra empresa.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problema"
            }
          }
        }
      },
      "ProblemaReferenciaAmbigua": {
        "description": "`referencia_ambigua`: a mesma `referencia` existe em mais de uma empresa da conta. Repita com `?empresa_id=`.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problema"
            }
          }
        }
      },
      "ProblemaNfceNaoEncontrada": {
        "description": "`nfce_nao_encontrada`: nenhuma NFC-e com esse id, referência ou chave de acesso nesta conta e neste ambiente.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problema"
            }
          }
        }
      },
      "ProblemaNfeNaoEncontrada": {
        "description": "`nfe_nao_encontrada`: nenhuma NF-e com esse id, referência ou chave de acesso nesta conta e neste ambiente.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problema"
            }
          }
        }
      },
      "ProblemaNfseNaoEncontrada": {
        "description": "`nfse_nao_encontrada`: nenhuma nota com esse id, referência ou chave de acesso nesta conta e neste ambiente.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problema"
            }
          }
        }
      },
      "ProblemaLoteNaoEncontrado": {
        "description": "`lote_nao_encontrado`.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problema"
            }
          }
        }
      },
      "ChaveDeTesteRecusada": {
        "description": "A chave de teste (`sdr_test_`) não faz esta operação: ela emite NFS-e e\nNF-e na homologação e lê empresas. Use uma chave de produção (`sdr_live_`).\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Erro"
            }
          }
        }
      },
      "NaoAutenticado": {
        "description": "Chave de API ausente, inválida ou revogada.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Erro"
            },
            "example": {
              "statusCode": 401,
              "message": "Chave de API inválida ou revogada.",
              "error": "Unauthorized"
            }
          }
        }
      },
      "NaoEncontrado": {
        "description": "Recurso não encontrado nesta conta.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Erro"
            },
            "example": {
              "statusCode": 404,
              "message": "Empresa não encontrada nesta conta.",
              "error": "Not Found"
            }
          }
        }
      },
      "RequisicaoInvalida": {
        "description": "Corpo ou parâmetros inválidos.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Erro"
            },
            "example": {
              "statusCode": 400,
              "message": [
                "cnpj must be longer than or equal to 11 characters"
              ],
              "error": "Bad Request"
            }
          }
        }
      }
    },
    "schemas": {
      "Dinheiro": {
        "type": "string",
        "pattern": "^\\d{1,13}(\\.\\d{1,2})?$",
        "description": "Texto decimal com ponto, sem separador de milhar. Número JSON é recusado (422 `tipo_invalido`).",
        "example": "1500.00"
      },
      "Aliquota": {
        "type": "string",
        "pattern": "^\\d{1,3}(\\.\\d{1,4})?$",
        "description": "Percentual como texto, com ponto e sem \"%\".",
        "example": "2.5"
      },
      "Tributo": {
        "type": "object",
        "description": "Informe o valor OU a alíquota. Com a alíquota, calculamos o valor sobre o valor do serviço.",
        "properties": {
          "valor": {
            "$ref": "#/components/schemas/Dinheiro"
          },
          "aliquota": {
            "$ref": "#/components/schemas/Aliquota"
          }
        }
      },
      "NfseEntrada": {
        "type": "object",
        "description": "O mesmo conjunto de campos da planilha de emissão, em JSON. Só\n`tomador.documento` e `valor` são sempre obrigatórios; `descricao`\ne `codigo_nacional` vêm da configuração da empresa quando omitidos.\nCampo desconhecido é erro (422 `campo_desconhecido`).\n",
        "required": [
          "tomador",
          "valor"
        ],
        "additionalProperties": false,
        "properties": {
          "empresa_id": {
            "type": "string",
            "description": "Empresa emissora. Dispensado quando a chave de API é restrita a uma empresa."
          },
          "referencia": {
            "type": "string",
            "maxLength": 60,
            "description": "Seu identificador para esta nota (pedido, contrato). Único por empresa; repetido é 409 com o id da nota existente."
          },
          "modelo": {
            "type": "string",
            "description": "Nome ou id de um modelo de emissão salvo no painel. Preenche descrição, código de serviço e competência quando não enviados."
          },
          "substituicao": {
            "type": "object",
            "additionalProperties": false,
            "description": "Esta nota SUBSTITUI uma NFS-e autorizada (grupo `subst` da DPS).\nInforme `nfse_id` (nota emitida pela Sudrel) ou `chave_acesso`\n(NFS-e emitida em outro sistema, do mesmo prestador). Veja \"Substituir\numa NFS-e\" acima. Só em `POST /v1/nfse`: o lote recusa\n(`substituicao_fora_do_lote`).\n",
            "required": [
              "codigo_motivo"
            ],
            "properties": {
              "nfse_id": {
                "type": "string",
                "description": "Id da nota a substituir (de `GET /v1/nfse`)."
              },
              "chave_acesso": {
                "type": "string",
                "description": "Ou a chave de acesso da NFS-e a substituir, 50 dígitos."
              },
              "codigo_motivo": {
                "type": "string",
                "enum": [
                  "01",
                  "02",
                  "03",
                  "04",
                  "05",
                  "99"
                ],
                "description": "01 desenquadramento do Simples Nacional; 02 enquadramento no Simples\nNacional; 03 inclusão retroativa de imunidade ou isenção; 04 exclusão\nretroativa de imunidade ou isenção; 05 rejeição da NFS-e pelo tomador\nou intermediário; 99 outros.\n"
              },
              "motivo": {
                "type": "string",
                "minLength": 15,
                "maxLength": 255,
                "description": "Descrição do motivo. Obrigatória com `codigo_motivo` 99 (E0078)."
              }
            }
          },
          "tomador": {
            "type": "object",
            "required": [
              "documento"
            ],
            "additionalProperties": false,
            "properties": {
              "documento": {
                "type": "string",
                "description": "CPF (11 dígitos) ou CNPJ (14 posições, numérico ou alfanumérico), com ou sem pontuação.",
                "example": "11222333000181"
              },
              "razao_social": {
                "type": "string",
                "description": "Obrigatório para CPF. Para CNPJ, consultamos automaticamente."
              },
              "email": {
                "type": "string",
                "description": "Obrigatório só quando o sistema do município da empresa precisa dele para cancelar a nota (hoje, o WebISS). Nos outros casos, opcional; quando vier, o PDF da nota vai para ele."
              },
              "endereco": {
                "type": "object",
                "additionalProperties": false,
                "description": "Para CPF, opcional: CPF e nome bastam, menos quando o serviço tributa no domicílio do tomador (o `cIndOp` aponta para o endereço dele, ou mão de obra, 17.05.01), e aí a validação devolve `tomador_endereco_obrigatorio`. Quando vier, CEP e número vão juntos e o resto sai do CEP. Para CNPJ, não precisa.",
                "properties": {
                  "cep": {
                    "type": "string",
                    "example": "40020000"
                  },
                  "numero": {
                    "type": "string"
                  },
                  "complemento": {
                    "type": "string"
                  },
                  "municipio": {
                    "type": "string",
                    "description": "Só para sobrescrever o município resolvido. Nome com UF ou código IBGE."
                  }
                }
              }
            }
          },
          "valor": {
            "$ref": "#/components/schemas/Dinheiro"
          },
          "servico": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "descricao": {
                "type": "string"
              },
              "codigo_nacional": {
                "type": "string",
                "description": "Código de tributação nacional (cTribNac), 6 dígitos.",
                "example": "010701"
              },
              "competencia": {
                "type": "string",
                "description": "AAAA-MM. Padrão, o mês atual.",
                "example": "2026-09"
              },
              "nbs": {
                "type": "string",
                "description": "Código NBS do serviço (9 dígitos, com ou sem pontos), declarado\njunto do IBS e da CBS. Tem de ser um dos admitidos para o código de\nserviço (veja `GET /v1/servicos/{codigo}/nbs`); cada NBS leva a sua\nclassificação tributária. Padrão: o NBS padrão da empresa, e na\nfalta dele o padrão da tabela oficial.\n",
                "example": "1.1302.21.00"
              },
              "obra": {
                "$ref": "#/components/schemas/ObraEntrada"
              }
            }
          },
          "retencoes": {
            "type": "object",
            "additionalProperties": false,
            "description": "O que o TOMADOR retém.",
            "properties": {
              "iss": {
                "type": "boolean",
                "description": "ISS retido pelo tomador."
              },
              "pis": {
                "$ref": "#/components/schemas/Tributo"
              },
              "cofins": {
                "$ref": "#/components/schemas/Tributo"
              },
              "csll": {
                "$ref": "#/components/schemas/Tributo"
              },
              "irrf": {
                "$ref": "#/components/schemas/Tributo"
              },
              "inss": {
                "$ref": "#/components/schemas/Tributo"
              }
            }
          },
          "apuracao_propria": {
            "type": "object",
            "additionalProperties": false,
            "description": "PIS/COFINS da apuração da SUA empresa (não é retenção).",
            "properties": {
              "pis": {
                "$ref": "#/components/schemas/Tributo"
              },
              "cofins": {
                "$ref": "#/components/schemas/Tributo"
              }
            }
          },
          "iss": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "aliquota": {
                "$ref": "#/components/schemas/Aliquota"
              }
            }
          }
        }
      },
      "ObraEntrada": {
        "type": "object",
        "additionalProperties": false,
        "description": "Dados da obra (grupo `serv/obra` da DPS). Obrigatório nos códigos de\nconstrução civil (E0370) e proibido nos demais, menos o 99.01.01\n(E0372). Identifique a obra por UM destes: `cno`, `cib` ou `endereco`\n(CEP e número); com mais de um, vai o CNO, depois o CIB. O município da\nobra é o local da prestação: vem do CEP, quando há CEP, ou de\n`municipio`.\n",
        "properties": {
          "cno": {
            "type": "string",
            "description": "Número da obra no Cadastro Nacional de Obras (ou CEI), com ou sem máscara."
          },
          "cib": {
            "type": "string",
            "description": "Código do Cadastro Imobiliário Brasileiro do imóvel, 8 caracteres."
          },
          "inscricao_imobiliaria": {
            "type": "string",
            "maxLength": 30,
            "description": "Inscrição imobiliária fiscal (a do IPTU), opcional."
          },
          "endereco": {
            "type": "object",
            "additionalProperties": false,
            "description": "Rua e bairro vêm do CEP.",
            "properties": {
              "cep": {
                "type": "string",
                "example": "40020000"
              },
              "numero": {
                "type": "string"
              },
              "complemento": {
                "type": "string"
              }
            }
          },
          "municipio": {
            "type": "string",
            "description": "Nome com UF (`Salvador - BA`) ou código IBGE. Dispensado quando o CEP foi informado; com os dois, têm de concordar (E0380)."
          }
        }
      },
      "ObraNfse": {
        "type": "object",
        "nullable": true,
        "properties": {
          "cno": {
            "type": "string",
            "nullable": true
          },
          "cib": {
            "type": "string",
            "nullable": true
          },
          "inscricao_imobiliaria": {
            "type": "string",
            "nullable": true
          },
          "endereco": {
            "type": "object",
            "nullable": true,
            "properties": {
              "cep": {
                "type": "string"
              },
              "logradouro": {
                "type": "string"
              },
              "numero": {
                "type": "string"
              },
              "complemento": {
                "type": "string",
                "nullable": true
              },
              "bairro": {
                "type": "string"
              }
            }
          },
          "municipio_ibge": {
            "type": "string",
            "description": "Local da prestação."
          }
        }
      },
      "Ajuste": {
        "type": "object",
        "description": "O que a Sudrel preencheu, derivou, omitiu ou exigiu, e por quê.",
        "properties": {
          "campo": {
            "type": "string",
            "description": "JSON Pointer.",
            "example": "/prestador/inscricao_municipal"
          },
          "acao": {
            "type": "string",
            "enum": [
              "preenchido",
              "omitido",
              "derivado",
              "exigido"
            ]
          },
          "motivo": {
            "type": "string"
          },
          "regra": {
            "type": "string",
            "description": "Identificador estável da regra.",
            "example": "correcao.E0120"
          }
        }
      },
      "EventoNfse": {
        "type": "object",
        "properties": {
          "tipo": {
            "type": "string",
            "enum": [
              "criada",
              "envio",
              "consulta_dps",
              "correcao_automatica",
              "reenfileirada",
              "falha_validacao",
              "recuperada",
              "cancelada",
              "substituida",
              "aguardando_confirmacao",
              "competencia_confirmada",
              "processamento_prolongado",
              "falha_transmissao"
            ]
          },
          "em": {
            "type": "string",
            "format": "date-time"
          },
          "detalhe": {
            "type": "object"
          }
        }
      },
      "Nfse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "referencia": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "transmitindo",
              "autorizada",
              "rejeitada",
              "cancelada",
              "falha_transmissao",
              "descartada",
              "aguardando_confirmacao"
            ]
          },
          "empresa_id": {
            "type": "string"
          },
          "ambiente": {
            "type": "string",
            "enum": [
              "producao",
              "sandbox"
            ],
            "description": "`sandbox` = emitida com chave de teste, no ambiente de testes do Sistema Nacional, sem valor fiscal."
          },
          "simulacao": {
            "type": "string",
            "nullable": true,
            "description": "Cenário do simulador de falhas (`X-Sudrel-Simular`); `null` em nota de verdade. Nota simulada nunca foi à Sefin."
          },
          "origem": {
            "type": "string",
            "enum": [
              "api",
              "planilha",
              "manual",
              "monitoramento"
            ]
          },
          "numero": {
            "type": "string",
            "nullable": true
          },
          "chave_acesso": {
            "type": "string",
            "nullable": true
          },
          "dps": {
            "type": "object",
            "nullable": true,
            "properties": {
              "serie": {
                "type": "string"
              },
              "numero": {
                "type": "string"
              }
            }
          },
          "valor": {
            "$ref": "#/components/schemas/Dinheiro"
          },
          "tomador": {
            "type": "object"
          },
          "servico": {
            "type": "object",
            "properties": {
              "codigo_nacional": {
                "type": "string"
              },
              "descricao": {
                "type": "string"
              },
              "competencia": {
                "type": "string",
                "example": "2026-10"
              },
              "nbs": {
                "type": "string",
                "nullable": true,
                "description": "NBS escolhido para a nota, sem pontos. `null` = padrão da empresa ou da tabela oficial; o que foi declarado aparece nos `ajustes`."
              },
              "obra": {
                "$ref": "#/components/schemas/ObraNfse"
              }
            }
          },
          "retencoes": {
            "type": "object"
          },
          "apuracao_propria": {
            "type": "object"
          },
          "iss": {
            "type": "object"
          },
          "rejeicao": {
            "type": "object",
            "nullable": true,
            "properties": {
              "codigo_oficial": {
                "type": "string",
                "nullable": true
              },
              "mensagem": {
                "type": "string",
                "description": "A mensagem do Sistema Nacional, como veio."
              },
              "explicacao": {
                "type": "object",
                "nullable": true,
                "description": "Explicação da Sudrel para o código oficial, quando ele é\nconhecido. `null` quando não é: aí vale só a `mensagem`.\n",
                "properties": {
                  "codigo": {
                    "type": "string",
                    "description": "Estável, ex.: `aliquota_iss_obrigatoria`.",
                    "example": "inscricao_municipal_obrigatoria"
                  },
                  "campo": {
                    "type": "string",
                    "nullable": true,
                    "description": "JSON Pointer no payload, quando é campo que você envia.",
                    "example": "/prestador/inscricao_municipal"
                  },
                  "mensagem": {
                    "type": "string"
                  },
                  "correcao": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "falha": {
            "type": "object",
            "nullable": true,
            "description": "Só em `falha_transmissao`.",
            "properties": {
              "dps_enviada": {
                "type": "string",
                "enum": [
                  "nao",
                  "desconhecido"
                ]
              },
              "mensagem": {
                "type": "string",
                "nullable": true
              },
              "correcao": {
                "type": "string"
              }
            }
          },
          "cancelamento": {
            "type": "object",
            "nullable": true,
            "properties": {
              "em": {
                "type": "string",
                "format": "date-time"
              },
              "protocolo": {
                "type": "string"
              },
              "justificativa": {
                "type": "string"
              }
            }
          },
          "recuperada_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "substituicao": {
            "type": "object",
            "nullable": true,
            "description": "Nesta nota (a nova), qual NFS-e ela substitui.",
            "properties": {
              "nfse_id": {
                "type": "string",
                "nullable": true,
                "description": "`null` quando a original foi emitida fora da Sudrel."
              },
              "chave_acesso": {
                "type": "string"
              },
              "codigo_motivo": {
                "type": "string"
              },
              "motivo": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "substituida_por": {
            "type": "object",
            "nullable": true,
            "description": "Nesta nota (a original, agora `cancelada` pelo Sistema Nacional), qual a substituiu.",
            "properties": {
              "nfse_id": {
                "type": "string"
              },
              "links": {
                "type": "object",
                "properties": {
                  "self": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "confirmacao": {
            "type": "object",
            "nullable": true,
            "description": "Só em `aguardando_confirmacao`.",
            "properties": {
              "motivo": {
                "type": "string",
                "enum": [
                  "competencia_encerrada"
                ]
              },
              "competencia": {
                "type": "string",
                "example": "2026-09"
              },
              "mensagem": {
                "type": "string"
              },
              "correcao": {
                "type": "string"
              }
            }
          },
          "aviso": {
            "type": "object",
            "nullable": true,
            "description": "Só em `transmitindo`, depois de 30 minutos.",
            "properties": {
              "codigo": {
                "type": "string",
                "enum": [
                  "processamento_prolongado"
                ]
              },
              "desde": {
                "type": "string",
                "format": "date-time"
              },
              "mensagem": {
                "type": "string"
              }
            }
          },
          "ajustes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Ajuste"
            }
          },
          "eventos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventoNfse"
            }
          },
          "regras_versao": {
            "type": "string",
            "description": "Versões do catálogo de correções automáticas e do catálogo de regras de campo que decidiram esta nota, nessa ordem.",
            "example": "2026-09-30.1+2026-10-02.1"
          },
          "criada_em": {
            "type": "string",
            "format": "date-time"
          },
          "atualizada_em": {
            "type": "string",
            "format": "date-time"
          },
          "links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string"
              },
              "xml": {
                "type": "string"
              },
              "pdf": {
                "type": "string"
              }
            }
          }
        }
      },
      "ItemProntidao": {
        "type": "object",
        "properties": {
          "item": {
            "type": "string",
            "description": "Estável. Novos itens podem aparecer.",
            "enum": [
              "certificado",
              "convenio_municipio",
              "regime_tributario",
              "regime_apuracao_simples",
              "municipio_emissao",
              "serie_dps",
              "padroes_emissao",
              "plano_emissao",
              "parametros_municipais",
              "sandbox_municipio_proprio",
              "nbs",
              "reducao_ibs_cbs",
              "token_municipio"
            ]
          },
          "situacao": {
            "type": "string",
            "enum": [
              "ok",
              "aviso",
              "bloqueio"
            ]
          },
          "mensagem": {
            "type": "string"
          },
          "correcao": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "Lote": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "tipo": {
            "type": "string",
            "enum": [
              "nfse",
              "nfe"
            ],
            "description": "O que o lote emite. No de NF-e, `contagens` conta notas e traz `linhas` (os itens das notas)."
          },
          "status": {
            "type": "string",
            "enum": [
              "validando",
              "aguardando_emissao",
              "processando",
              "concluido",
              "erro"
            ],
            "description": "`validando` → (`aguardando_emissao`, só com `ao_validar: \"aguardar\"`) →\n`processando` → `concluido`. `concluido` quer dizer que nenhuma nota\ndo lote está mais transmitindo; pode haver rejeitadas e linhas com erro.\n"
          },
          "empresa_id": {
            "type": "string"
          },
          "ambiente": {
            "type": "string",
            "enum": [
              "producao",
              "sandbox"
            ]
          },
          "origem": {
            "type": "string",
            "enum": [
              "api",
              "painel"
            ]
          },
          "formato": {
            "type": "string",
            "enum": [
              "json",
              "planilha"
            ]
          },
          "ao_validar": {
            "type": "string",
            "enum": [
              "emitir_validas",
              "aguardar"
            ],
            "nullable": true
          },
          "contagens": {
            "type": "object",
            "description": "Linhas por status. `total` é o número de linhas recebidas.",
            "properties": {
              "total": {
                "type": "integer"
              },
              "transmitindo": {
                "type": "integer"
              },
              "autorizada": {
                "type": "integer"
              },
              "rejeitada": {
                "type": "integer"
              },
              "falha_transmissao": {
                "type": "integer"
              },
              "aguardando_confirmacao": {
                "type": "integer"
              },
              "cancelada": {
                "type": "integer"
              },
              "descartada": {
                "type": "integer"
              },
              "com_erro_validacao": {
                "type": "integer"
              },
              "aguardando_emissao": {
                "type": "integer"
              },
              "ja_existente": {
                "type": "integer"
              }
            }
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "validado_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "emissao_disparada_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "concluido_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string"
              },
              "itens": {
                "type": "string"
              },
              "relatorio": {
                "type": "string"
              }
            }
          }
        }
      },
      "StatusItemLote": {
        "type": "string",
        "enum": [
          "transmitindo",
          "autorizada",
          "rejeitada",
          "cancelada",
          "falha_transmissao",
          "descartada",
          "aguardando_confirmacao",
          "com_erro_validacao",
          "aguardando_emissao",
          "ja_existente"
        ]
      },
      "ItemLote": {
        "type": "object",
        "properties": {
          "linha": {
            "type": "integer",
            "description": "Linha da planilha (cabeçalho = 1) ou posição no array JSON (a partir de 1)."
          },
          "referencia": {
            "type": "string",
            "nullable": true
          },
          "nfse_id": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "$ref": "#/components/schemas/StatusItemLote"
          },
          "numero": {
            "type": "string",
            "nullable": true
          },
          "chave_acesso": {
            "type": "string",
            "nullable": true
          },
          "erros": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ErroCampo"
            }
          },
          "ajustes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Ajuste"
            }
          },
          "divergente": {
            "type": "boolean",
            "description": "Só em `ja_existente`: o conteúdo da linha difere da nota que já existe."
          },
          "status_nfse": {
            "type": "string",
            "description": "Só em `ja_existente`: o status atual da nota que já existe."
          }
        }
      },
      "WebhookEntrada": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "URL completa, http(s). Endereço de rede interna é recusado."
          },
          "eventos": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ativo": {
            "type": "boolean"
          },
          "cabecalhos": {
            "type": "array",
            "maxItems": 5,
            "items": {
              "type": "object",
              "required": [
                "nome",
                "valor"
              ],
              "properties": {
                "nome": {
                  "type": "string",
                  "maxLength": 64
                },
                "valor": {
                  "type": "string",
                  "maxLength": 1024
                }
              }
            }
          }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "eventos": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ativo": {
            "type": "boolean"
          },
          "ambiente": {
            "type": "string",
            "enum": [
              "producao",
              "sandbox"
            ]
          },
          "cabecalhos": {
            "type": "array",
            "description": "Só os nomes; o valor nunca volta.",
            "items": {
              "type": "object",
              "properties": {
                "nome": {
                  "type": "string"
                }
              }
            }
          },
          "segredo_anterior_valido_ate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "ultimo_sucesso_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "aviso_falha_enviado_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string"
              },
              "entregas": {
                "type": "string"
              }
            }
          }
        }
      },
      "EntregaWebhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "O `X-Sudrel-Delivery-Id`."
          },
          "evento_id": {
            "type": "string",
            "description": "O `X-Sudrel-Event-Id`."
          },
          "tipo": {
            "type": "string"
          },
          "origem": {
            "type": "string",
            "enum": [
              "automatica",
              "reenvio"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "sucesso",
              "pendente",
              "falhou"
            ]
          },
          "tentativas": {
            "type": "integer"
          },
          "ultimo_status_http": {
            "type": "integer",
            "nullable": true,
            "description": "`null` quando não houve resposta (conexão, tempo)."
          },
          "ultima_tentativa_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "proxima_tentativa_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "falhou_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "EventoConta": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "O mesmo `X-Sudrel-Event-Id` das entregas."
          },
          "seq": {
            "type": "string",
            "description": "Posição no log (o cursor)."
          },
          "tipo": {
            "type": "string"
          },
          "ocorrido_em": {
            "type": "string",
            "format": "date-time"
          },
          "ambiente": {
            "type": "string",
            "enum": [
              "producao",
              "sandbox"
            ]
          },
          "empresa_id": {
            "type": "string",
            "nullable": true
          },
          "recurso": {
            "type": "object",
            "properties": {
              "tipo": {
                "type": "string",
                "enum": [
                  "nfse",
                  "lote",
                  "empresa",
                  "documento",
                  "pendencia_ecac"
                ]
              },
              "id": {
                "type": "string"
              },
              "url": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "dados": {
            "type": "object",
            "nullable": true,
            "description": "O corpo do webhook, quando foi guardado."
          }
        }
      },
      "ErroCampo": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "`https://sudrel.com.br/docs/erros/<codigo>`. Não vem nos itens de `erros` do 422 de `POST /v1/lotes`."
          },
          "codigo": {
            "type": "string",
            "description": "Estável: programe em cima dele."
          },
          "codigo_oficial": {
            "type": "string",
            "nullable": true,
            "description": "Regra do Sistema Nacional antecipada, quando houver (ex.: E0202)."
          },
          "campo": {
            "type": "string",
            "nullable": true,
            "description": "JSON Pointer no payload."
          },
          "mensagem": {
            "type": "string"
          },
          "correcao": {
            "type": "string",
            "nullable": true
          },
          "retentavel": {
            "type": "boolean",
            "description": "Repetir a MESMA requisição pode dar certo?"
          }
        }
      },
      "ProdutoEntrada": {
        "type": "object",
        "properties": {
          "empresa_id": {
            "type": "string"
          },
          "codigo": {
            "type": "string",
            "maxLength": 60,
            "description": "Seu código (SKU), único por empresa."
          },
          "descricao": {
            "type": "string",
            "maxLength": 120
          },
          "ncm": {
            "type": "string",
            "pattern": "^[0-9]{8}$"
          },
          "cest": {
            "type": "string",
            "nullable": true
          },
          "gtin": {
            "type": "string",
            "nullable": true,
            "description": "GTIN-8, 12, 13 ou 14, ou \"SEM GTIN\"."
          },
          "origem": {
            "type": "string",
            "default": "0"
          },
          "unidade": {
            "type": "string"
          },
          "unidade_tributavel": {
            "type": "string",
            "nullable": true
          },
          "c_benef": {
            "type": "string",
            "nullable": true,
            "description": "Código de benefício fiscal da UF. A Bahia não exige; guardado como veio."
          },
          "ex_tipi": {
            "type": "string",
            "nullable": true,
            "description": "Exceção da TIPI. \"\" = nenhuma (declarado)."
          },
          "producao_propria": {
            "type": "boolean",
            "default": false
          },
          "ativo": {
            "type": "boolean"
          },
          "perfil_fiscal_nome": {
            "type": "string",
            "description": "O nome de um perfil fiscal JÁ aprovado da empresa (criado e aprovado no painel,\nem Emissão de NF-e › Produtos e perfis). O produto copia o tratamento e a\naprovação do perfil. Mande `perfil_fiscal` OU `perfil_fiscal_nome`.\nRecusas: `perfil_fiscal_nao_encontrado`, `perfil_fiscal_nao_aprovado`.\n"
          },
          "perfil_fiscal": {
            "type": "object",
            "properties": {
              "icms": {
                "type": "string",
                "enum": [
                  "tributado",
                  "base_reduzida",
                  "isento",
                  "nao_tributado",
                  "imune",
                  "st_retida",
                  "st_substituto"
                ]
              },
              "pis_cofins": {
                "type": "string",
                "enum": [
                  "tributado",
                  "monofasico",
                  "aliquota_zero",
                  "outros"
                ]
              },
              "termo_acordo": {
                "type": "boolean",
                "default": false,
                "description": "Produto das atividades do Anexo Único do Decreto 7.799/2000 (Termo de Acordo de atacadista da BA)."
              },
              "ibs_cbs": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "cst": {
                    "type": "string"
                  },
                  "classificacao_tributaria": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      },
      "Produto": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ProdutoEntrada"
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "ambiente": {
                "type": "string",
                "enum": [
                  "producao",
                  "sandbox"
                ],
                "description": "Cadastro a que o produto pertence (o da chave que o criou)."
              },
              "gtin_sefaz": {
                "type": "object",
                "nullable": true,
                "description": "O que o Cadastro Centralizado de GTIN da SEFAZ devolveu (cStat, descrição, NCM e CEST)."
              },
              "gtin_conferido_em": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "perfil_fiscal": {
                "type": "object",
                "properties": {
                  "aprovado": {
                    "type": "boolean"
                  },
                  "aprovado_por": {
                    "type": "string",
                    "nullable": true
                  },
                  "aprovado_em": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true
                  }
                }
              },
              "criado_em": {
                "type": "string",
                "format": "date-time"
              },
              "atualizado_em": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        ]
      },
      "PerfilFiscalNfe": {
        "type": "object",
        "properties": {
          "empresa_id": {
            "type": "string"
          },
          "regime_pis_cofins": {
            "type": "string",
            "enum": [
              "cumulativo",
              "nao_cumulativo"
            ],
            "nullable": true
          },
          "contribuinte_ipi": {
            "type": "boolean"
          },
          "isencao_faixa_simples": {
            "type": "boolean",
            "description": "CSOSN 103 (isenção do ICMS para a faixa de receita)."
          },
          "credito_simples": {
            "type": "object",
            "nullable": true,
            "description": "CSOSN 101: alíquota de crédito do mês (LC 123/2006, art. 23).",
            "properties": {
              "competencia": {
                "type": "string",
                "example": "2026-10"
              },
              "aliquota": {
                "type": "number"
              }
            }
          },
          "recusar_divergencias": {
            "type": "boolean",
            "description": "Modo conferir: recusar a nota com divergência (padrão: emitir e avisar)."
          },
          "politica_contingencia": {
            "type": "string",
            "enum": [
              "esperar",
              "svc",
              "epec"
            ],
            "default": "esperar",
            "description": "O que fazer com a nota que nunca saiu quando a SEFAZ da UF cai (veja Contingência da NF-e). Não apaga a aprovação."
          },
          "exclui_icms_base_pis_cofins": {
            "type": "boolean",
            "default": true,
            "description": "Base do PIS/COFINS sem o ICMS destacado (Tema 69 do STF). false = ICMS na base."
          },
          "termo_acordo": {
            "type": "object",
            "nullable": true,
            "description": "Credenciamento de atacadista no Decreto 7.799/2000 (art. 7º). null = sem Termo.",
            "properties": {
              "numero": {
                "type": "string"
              },
              "item_anexo": {
                "type": "string",
                "description": "Item do Anexo Único, de 1 a 16."
              },
              "vigente_de": {
                "type": "string",
                "format": "date"
              },
              "vigente_ate": {
                "type": "string",
                "format": "date",
                "nullable": true
              }
            }
          },
          "aprovado": {
            "type": "boolean"
          },
          "aprovado_por": {
            "type": "string",
            "nullable": true
          },
          "aprovado_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "Aprovacao": {
        "type": "object",
        "required": [
          "aprovado_por"
        ],
        "properties": {
          "aprovado_por": {
            "type": "object",
            "required": [
              "nome",
              "email"
            ],
            "properties": {
              "nome": {
                "type": "string"
              },
              "email": {
                "type": "string"
              }
            }
          }
        },
        "example": {
          "aprovado_por": {
            "nome": "Ana Souza",
            "email": "ana@escritorio.com.br"
          }
        }
      },
      "NfeItemCalculado": {
        "type": "object",
        "description": "Item dos modos calcular e conferir (no conferir, mais os campos do item informado).",
        "required": [
          "produto",
          "quantidade",
          "valor_unitario"
        ],
        "properties": {
          "produto": {
            "type": "string",
            "description": "Código do produto em /v1/produtos."
          },
          "quantidade": {
            "type": "number"
          },
          "valor_unitario": {
            "type": "number"
          },
          "desconto": {
            "type": "number"
          },
          "frete": {
            "type": "number"
          },
          "seguro": {
            "type": "number"
          },
          "outras_despesas": {
            "type": "number"
          },
          "informacoes_adicionais": {
            "type": "string"
          },
          "st_retido": {
            "type": "object",
            "description": "ICMS-ST retido anteriormente na revenda (CST 60 / CSOSN 500). Prevalece sobre o que viria das entradas vinculadas.",
            "properties": {
              "base_calculo": {
                "type": "number"
              },
              "aliquota": {
                "type": "number"
              },
              "valor_substituto": {
                "type": "number"
              },
              "valor": {
                "type": "number"
              }
            }
          }
        }
      },
      "EstadoUfSefaz": {
        "type": "object",
        "properties": {
          "uf": {
            "type": "string"
          },
          "ambiente": {
            "type": "string",
            "enum": [
              "producao",
              "sandbox"
            ]
          },
          "estado": {
            "type": "string",
            "enum": [
              "normal",
              "instavel",
              "indisponivel"
            ]
          },
          "motivo": {
            "type": "string",
            "nullable": true
          },
          "status_servico": {
            "type": "object",
            "nullable": true,
            "properties": {
              "cstat": {
                "type": "string"
              },
              "motivo": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "transmissoes_15min": {
            "type": "integer"
          },
          "falhas_15min": {
            "type": "integer"
          },
          "contingencia": {
            "type": "object",
            "properties": {
              "autorizador": {
                "type": "string",
                "enum": [
                  "SVC-AN",
                  "SVC-RS"
                ]
              },
              "svc_ativa": {
                "type": "boolean"
              },
              "cstat": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "avaliado_em": {
            "type": "string",
            "format": "date-time"
          },
          "desde": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "VinculoEntradaProduto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "criterio": {
            "type": "string",
            "enum": [
              "gtin",
              "codigo_fornecedor",
              "manual"
            ]
          },
          "gtin": {
            "type": "string",
            "nullable": true
          },
          "cnpj_fornecedor": {
            "type": "string",
            "nullable": true
          },
          "codigo_fornecedor": {
            "type": "string",
            "nullable": true
          },
          "item_nota_fiscal_id": {
            "type": "string",
            "nullable": true
          },
          "criado_por": {
            "type": "string",
            "nullable": true
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ForaDeCobertura": {
        "type": "object",
        "properties": {
          "item": {
            "type": "integer",
            "nullable": true,
            "description": "Número do item (1 em diante); null = a nota inteira."
          },
          "tributo": {
            "type": "string",
            "enum": [
              "operacao",
              "cfop",
              "icms",
              "ipi",
              "pis_cofins",
              "ibs_cbs",
              "perfil"
            ]
          },
          "motivo": {
            "type": "string"
          },
          "temporario": {
            "type": "boolean",
            "description": "Tentar de novo resolve (calculadora oficial fora do ar)."
          }
        }
      },
      "NfeEntrada": {
        "type": "object",
        "description": "Pedido de NF-e no modo `informado`: os tributos de cada item vêm prontos.\nCampos em português, `snake_case`. O que a Sudrel preencher aparece em\n`ajustes` na resposta.\n",
        "required": [
          "empresa_id",
          "natureza_operacao",
          "presenca",
          "destinatario",
          "itens",
          "pagamentos"
        ],
        "properties": {
          "empresa_id": {
            "type": "string"
          },
          "referencia": {
            "type": "string",
            "maxLength": 60,
            "description": "Seu identificador, único por empresa e ambiente."
          },
          "modo": {
            "type": "string",
            "enum": [
              "informado",
              "calcular",
              "conferir"
            ],
            "default": "informado"
          },
          "operacao": {
            "type": "string",
            "enum": [
              "venda",
              "venda_consumidor_final",
              "remessa",
              "transferencia",
              "bonificacao",
              "devolucao"
            ],
            "description": "Modos calcular e conferir. Padrão venda."
          },
          "subtipo": {
            "type": "string",
            "enum": [
              "conserto",
              "demonstracao",
              "industrializacao",
              "outras",
              "comercializacao"
            ],
            "description": "Remessa e devolução."
          },
          "chave_referenciada": {
            "type": "string",
            "description": "Chave de acesso da NF-e de origem (44 caracteres; pode ter letra com CNPJ alfanumérico). Obrigatória com `finalidade` `devolucao` ou `complementar` e com `operacao: devolucao`; aceita nas outras. Na devolução vai em cada item (`det/DFeReferenciado`); nas outras finalidades, em `NFref/refNFe`."
          },
          "serie": {
            "type": "integer",
            "minimum": 0,
            "maximum": 889,
            "description": "Omitida: a série da API desta empresa."
          },
          "natureza_operacao": {
            "type": "string",
            "maxLength": 60
          },
          "tipo_operacao": {
            "type": "string",
            "enum": [
              "saida",
              "entrada"
            ],
            "default": "saida"
          },
          "finalidade": {
            "type": "string",
            "enum": [
              "normal",
              "complementar",
              "ajuste",
              "devolucao"
            ],
            "default": "normal"
          },
          "presenca": {
            "type": "string",
            "enum": [
              "nao_se_aplica",
              "presencial",
              "internet",
              "telefone",
              "entrega_em_domicilio",
              "presencial_fora_do_estabelecimento",
              "outros"
            ]
          },
          "consumidor_final": {
            "type": "boolean",
            "default": false
          },
          "intermediador": {
            "type": "boolean",
            "description": "Só `false` nesta versão (venda pelo próprio canal)."
          },
          "destinatario": {
            "type": "object",
            "required": [
              "documento"
            ],
            "description": "Só o documento basta. Com CNPJ, a Sudrel completa `nome` e `endereco` pela\nconsulta pública do CNPJ (base da Receita Federal) e `contribuinte` e\n`inscricao_estadual` pelo cadastro da SEFAZ da UF do destinatário. Com CPF,\nmande `nome` e, no `endereco`, só `cep` e `numero`: rua, bairro e\ncidade vêm do CEP, e o CPF é `nao_contribuinte`. O que você mandar\nprevalece; o que a Sudrel preencheu volta em `ajustes` (regras\n`nfe_destinatario_*`). Sem resposta da SEFAZ sobre a inscrição estadual, a\nnota é recusada com `destinatario_ie_indisponivel` (retentável), nunca\nemitida com um palpite.\n",
            "properties": {
              "documento": {
                "type": "string",
                "description": "CPF ou CNPJ."
              },
              "nome": {
                "type": "string",
                "maxLength": 60,
                "description": "Obrigatório com CPF. Com CNPJ, vem da Receita se faltar."
              },
              "contribuinte": {
                "type": "string",
                "enum": [
                  "contribuinte",
                  "isento",
                  "nao_contribuinte"
                ],
                "description": "Sem ele, a Sudrel consulta a SEFAZ (CNPJ) ou usa `nao_contribuinte` (CPF)."
              },
              "inscricao_estadual": {
                "type": "string",
                "description": "Obrigatória com `contribuinte`."
              },
              "optante_simples": {
                "type": "boolean",
                "description": "Modo calcular: o destinatário é ME/EPP? Exigido na venda interna do fabricante a contribuinte (alíquota de 7% da Bahia)."
              },
              "email": {
                "type": "string"
              },
              "endereco": {
                "type": "object",
                "description": "Completo, ou só `cep` e `numero` (o resto vem do CEP). Com CNPJ, pode faltar inteiro (vem da Receita).",
                "properties": {
                  "logradouro": {
                    "type": "string"
                  },
                  "numero": {
                    "type": "string"
                  },
                  "complemento": {
                    "type": "string"
                  },
                  "bairro": {
                    "type": "string"
                  },
                  "municipio_ibge": {
                    "type": "string"
                  },
                  "municipio": {
                    "type": "string"
                  },
                  "uf": {
                    "type": "string",
                    "description": "`EX` para exterior."
                  },
                  "cep": {
                    "type": "string"
                  },
                  "telefone": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "itens": {
            "type": "array",
            "minItems": 1,
            "maxItems": 990,
            "items": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/NfeItem"
                },
                {
                  "$ref": "#/components/schemas/NfeItemCalculado"
                }
              ]
            }
          },
          "transporte": {
            "type": "object",
            "properties": {
              "modalidade": {
                "type": "string",
                "enum": [
                  "emitente",
                  "destinatario",
                  "terceiros",
                  "proprio_emitente",
                  "proprio_destinatario",
                  "sem_frete"
                ],
                "default": "sem_frete"
              }
            }
          },
          "totais": {
            "type": "object",
            "description": "Opcional. O que você mandar é conferido contra a soma dos itens; o que faltar é somado.",
            "properties": {
              "valor_produtos": {
                "type": "number"
              },
              "valor_nota": {
                "type": "number"
              },
              "base_icms": {
                "type": "number"
              },
              "valor_icms": {
                "type": "number"
              },
              "valor_desconto": {
                "type": "number"
              },
              "valor_frete": {
                "type": "number"
              },
              "valor_seguro": {
                "type": "number"
              },
              "outras_despesas": {
                "type": "number"
              },
              "valor_pis": {
                "type": "number"
              },
              "valor_cofins": {
                "type": "number"
              },
              "ibs_cbs": {
                "type": "object",
                "properties": {
                  "base_calculo": {
                    "type": "number"
                  },
                  "ibs_uf": {
                    "type": "number"
                  },
                  "ibs_municipio": {
                    "type": "number"
                  },
                  "ibs": {
                    "type": "number"
                  },
                  "cbs": {
                    "type": "number"
                  }
                }
              }
            }
          },
          "pagamentos": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "forma",
                "valor"
              ],
              "properties": {
                "forma": {
                  "type": "string",
                  "enum": [
                    "dinheiro",
                    "cheque",
                    "cartao_credito",
                    "cartao_debito",
                    "credito_loja",
                    "vale_alimentacao",
                    "vale_refeicao",
                    "vale_presente",
                    "vale_combustivel",
                    "boleto",
                    "deposito",
                    "pix",
                    "pix_estatico",
                    "transferencia",
                    "programa_fidelidade",
                    "sem_pagamento",
                    "outros"
                  ],
                  "description": "`pix` é o Pix dinâmico (tPag 17); `pix_estatico` (tPag 20) é o QR fixo ou a chave."
                },
                "valor": {
                  "type": "number"
                }
              }
            }
          },
          "troco": {
            "type": "number"
          },
          "autorizados_xml": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "CPF/CNPJ autorizados a baixar o XML."
          },
          "informacoes_complementares": {
            "type": "string",
            "maxLength": 5000
          },
          "informacoes_fisco": {
            "type": "string",
            "maxLength": 2000
          }
        }
      },
      "NfeItem": {
        "type": "object",
        "required": [
          "codigo",
          "descricao",
          "ncm",
          "cfop",
          "origem",
          "unidade",
          "quantidade",
          "valor_unitario",
          "icms",
          "pis",
          "cofins"
        ],
        "properties": {
          "codigo": {
            "type": "string"
          },
          "descricao": {
            "type": "string"
          },
          "gtin": {
            "type": "string",
            "description": "Omitido: \"SEM GTIN\"."
          },
          "ncm": {
            "type": "string",
            "pattern": "^[0-9]{8}$"
          },
          "cest": {
            "type": "string"
          },
          "cfop": {
            "type": "string",
            "pattern": "^[0-9]{4}$"
          },
          "origem": {
            "type": "string",
            "description": "Origem da mercadoria, 0 a 8."
          },
          "unidade": {
            "type": "string"
          },
          "quantidade": {
            "type": "number"
          },
          "valor_unitario": {
            "type": "number"
          },
          "valor_total": {
            "type": "number",
            "description": "Omitido: quantidade vezes valor unitário."
          },
          "desconto": {
            "type": "number"
          },
          "frete": {
            "type": "number"
          },
          "seguro": {
            "type": "number"
          },
          "outras_despesas": {
            "type": "number"
          },
          "icms": {
            "type": "object",
            "description": "`cst` (00, 10, 20, 40, 41, 50, 60, 70) ou `csosn` (101, 102, 103, 300, 400, 500), com base, alíquota e valor quando o grupo pede. CST 10 e 70 exigem o grupo `st`.",
            "properties": {
              "cst": {
                "type": "string"
              },
              "csosn": {
                "type": "string"
              },
              "modalidade_base_calculo": {
                "type": "string"
              },
              "base_calculo": {
                "type": "number"
              },
              "aliquota": {
                "type": "number"
              },
              "valor": {
                "type": "number"
              },
              "reducao_base_calculo": {
                "type": "number",
                "description": "CST 20 e 70."
              },
              "fcp": {
                "type": "object",
                "description": "FECP (CST 00, 10, 20 e 70).",
                "properties": {
                  "base_calculo": {
                    "type": "number"
                  },
                  "aliquota": {
                    "type": "number"
                  },
                  "valor": {
                    "type": "number"
                  }
                }
              },
              "st": {
                "type": "object",
                "description": "ICMS-ST do substituto (CST 10 e 70).",
                "properties": {
                  "modalidade_base_calculo": {
                    "type": "string",
                    "default": "4"
                  },
                  "mva": {
                    "type": "number"
                  },
                  "reducao_base_calculo": {
                    "type": "number"
                  },
                  "base_calculo": {
                    "type": "number"
                  },
                  "aliquota": {
                    "type": "number"
                  },
                  "valor": {
                    "type": "number"
                  },
                  "fcp": {
                    "type": "object",
                    "properties": {
                      "base_calculo": {
                        "type": "number"
                      },
                      "aliquota": {
                        "type": "number"
                      },
                      "valor": {
                        "type": "number"
                      }
                    }
                  }
                }
              },
              "st_retido": {
                "type": "object",
                "description": "ICMS-ST retido anteriormente (CST 60 / CSOSN 500).",
                "properties": {
                  "base_calculo": {
                    "type": "number"
                  },
                  "aliquota": {
                    "type": "number"
                  },
                  "valor_substituto": {
                    "type": "number"
                  },
                  "valor": {
                    "type": "number"
                  }
                }
              }
            }
          },
          "pis": {
            "$ref": "#/components/schemas/NfePisCofins"
          },
          "cofins": {
            "$ref": "#/components/schemas/NfePisCofins"
          },
          "ex_tipi": {
            "type": "string",
            "description": "Exceção da TIPI (EXTIPI)."
          },
          "item_referenciado": {
            "type": "integer",
            "minimum": 1,
            "maximum": 990,
            "description": "Devolução: número deste item na nota de origem (`nItem`). Opcional; vai junto da chave da nota de origem no item."
          },
          "ipi": {
            "type": "object",
            "description": "Grupo IPI (acréscimo da fase 3). IPITrib com CST 00, 49, 50 ou 99; IPINT com CST 01 a 05 ou 51 a 55.",
            "properties": {
              "cst": {
                "type": "string"
              },
              "enquadramento": {
                "type": "string",
                "default": "999"
              },
              "base_calculo": {
                "type": "number"
              },
              "aliquota": {
                "type": "number"
              },
              "valor": {
                "type": "number"
              }
            }
          },
          "ibs_cbs": {
            "type": "object",
            "properties": {
              "cst": {
                "type": "string"
              },
              "classificacao_tributaria": {
                "type": "string"
              },
              "base_calculo": {
                "type": "number"
              },
              "ibs_uf": {
                "type": "object",
                "properties": {
                  "aliquota": {
                    "type": "number"
                  },
                  "valor": {
                    "type": "number"
                  }
                }
              },
              "ibs_municipio": {
                "type": "object",
                "properties": {
                  "aliquota": {
                    "type": "number"
                  },
                  "valor": {
                    "type": "number"
                  }
                }
              },
              "cbs": {
                "type": "object",
                "properties": {
                  "aliquota": {
                    "type": "number"
                  },
                  "valor": {
                    "type": "number"
                  }
                }
              }
            }
          }
        }
      },
      "NfePisCofins": {
        "type": "object",
        "required": [
          "cst"
        ],
        "properties": {
          "cst": {
            "type": "string"
          },
          "base_calculo": {
            "type": "number"
          },
          "aliquota": {
            "type": "number"
          },
          "valor": {
            "type": "number"
          }
        }
      },
      "NfceEntrada": {
        "type": "object",
        "description": "Pedido de NFC-e. Sem `modo`, a Sudrel calcula os tributos pelo produto cadastrado.",
        "required": [
          "referencia",
          "caixa",
          "itens",
          "pagamentos"
        ],
        "properties": {
          "empresa_id": {
            "type": "string",
            "description": "Dispensado com chave restrita a uma empresa."
          },
          "referencia": {
            "type": "string",
            "maxLength": 60,
            "description": "A venda no seu sistema; única por empresa, ambiente e modelo."
          },
          "caixa": {
            "type": "string",
            "description": "Identificador (ou id) do caixa: a série é a dele."
          },
          "modo": {
            "type": "string",
            "enum": [
              "calcular",
              "informado",
              "conferir"
            ],
            "default": "calcular"
          },
          "consumidor": {
            "type": "object",
            "description": "Opcional. Na BA, obrigatório a partir de R$ 500,00.",
            "properties": {
              "documento": {
                "type": "string",
                "description": "CPF ou CNPJ."
              },
              "nome": {
                "type": "string",
                "maxLength": 60
              },
              "email": {
                "type": "string",
                "maxLength": 60
              }
            }
          },
          "itens": {
            "type": "array",
            "description": "Modo calcular: `produto`, `quantidade`, `valor_unitario` e, se houver, `desconto`. Modos informado e conferir: o item da NF-e (`NfeEntrada`).",
            "items": {
              "type": "object"
            }
          },
          "pagamentos": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "forma"
              ],
              "properties": {
                "forma": {
                  "type": "string",
                  "description": "A forma da NF-e: dinheiro, pix, pix_estatico, cartao_credito, cartao_debito..."
                },
                "valor": {
                  "type": "number",
                  "description": "Num pagamento só, pode faltar (vira o valor da nota). O que passar do total vira troco."
                },
                "cartao": {
                  "type": "object",
                  "description": "Cartão e Pix. Sem este grupo, POS sem integração.",
                  "properties": {
                    "integrado": {
                      "type": "boolean"
                    },
                    "cnpj_credenciadora": {
                      "type": "string"
                    },
                    "bandeira": {
                      "type": "string",
                      "description": "tBand, 2 dígitos."
                    },
                    "autorizacao": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "informacoes_complementares": {
            "type": "string",
            "maxLength": 5000
          }
        }
      },
      "Nfce": {
        "type": "object",
        "description": "A NFC-e. Os campos da NF-e (`status`, `chave_acesso`, `protocolo`, `rejeicao`, `ajustes`, `eventos`...) mais os do modelo 65.",
        "properties": {
          "id": {
            "type": "string"
          },
          "referencia": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Os estados da NF-e. A lista cresce."
          },
          "modelo": {
            "type": "integer",
            "enum": [
              65
            ]
          },
          "modo": {
            "type": "string"
          },
          "serie": {
            "type": "integer"
          },
          "numero": {
            "type": "integer"
          },
          "chave_acesso": {
            "type": "string"
          },
          "protocolo": {
            "type": "string",
            "nullable": true
          },
          "valor_total": {
            "type": "string",
            "nullable": true
          },
          "troco": {
            "type": "string",
            "nullable": true
          },
          "caixa": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "string"
              },
              "identificador": {
                "type": "string"
              }
            }
          },
          "consumidor": {
            "type": "object",
            "nullable": true,
            "properties": {
              "documento": {
                "type": "string"
              },
              "nome": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "qr_code": {
            "type": "string",
            "nullable": true,
            "description": "O texto do QR Code (versão 3, ou 2 quando a UF recusa a 3)."
          },
          "url_consulta": {
            "type": "string",
            "nullable": true,
            "description": "Consulta pela chave de acesso na SEFAZ da UF."
          },
          "cancelavel_ate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string"
              },
              "xml": {
                "type": "string"
              },
              "danfe": {
                "type": "string"
              },
              "danfe_texto": {
                "type": "string"
              }
            }
          }
        }
      },
      "CaixaNfce": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "empresa_id": {
            "type": "string"
          },
          "identificador": {
            "type": "string"
          },
          "descricao": {
            "type": "string",
            "nullable": true
          },
          "serie": {
            "type": "integer"
          },
          "situacao": {
            "type": "string",
            "enum": [
              "ativo",
              "inativo"
            ]
          },
          "proximo_numero": {
            "type": "integer",
            "nullable": true,
            "description": "Próximo número da série do caixa; nulo antes da primeira NFC-e."
          },
          "desativado_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "atualizado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Nfe": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "referencia": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "transmitindo",
              "aguardando_confirmacao",
              "autorizada",
              "rejeitada",
              "denegada",
              "cancelada",
              "descartada",
              "contingencia_epec"
            ]
          },
          "empresa_id": {
            "type": "string"
          },
          "ambiente": {
            "type": "string",
            "enum": [
              "sandbox",
              "producao"
            ]
          },
          "simulacao": {
            "type": "string",
            "nullable": true
          },
          "modo": {
            "type": "string",
            "enum": [
              "informado",
              "calcular",
              "conferir"
            ]
          },
          "modelo": {
            "type": "integer",
            "enum": [
              55
            ]
          },
          "serie": {
            "type": "integer"
          },
          "numero": {
            "type": "integer"
          },
          "chave_acesso": {
            "type": "string"
          },
          "chaves_anteriores": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Chaves que a nota teve antes de uma correção num mês seguinte."
          },
          "chave_referenciada": {
            "type": "string",
            "nullable": true,
            "description": "Chave da NF-e de origem referenciada (devolução, complementar); null quando a nota não referencia nenhuma."
          },
          "protocolo": {
            "type": "string",
            "nullable": true
          },
          "emitida_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "autorizada_em": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "valor_total": {
            "type": "string",
            "nullable": true
          },
          "sefaz": {
            "type": "object",
            "nullable": true,
            "properties": {
              "cstat": {
                "type": "string"
              },
              "motivo": {
                "type": "string"
              }
            }
          },
          "rejeicao": {
            "$ref": "#/components/schemas/NfeRecusa"
          },
          "denegacao": {
            "$ref": "#/components/schemas/NfeRecusa"
          },
          "falha_envio": {
            "type": "object",
            "nullable": true,
            "description": "Nota em `transmitindo` que ainda não chegou à SEFAZ por uma falha antes do\nenvio. Com `certificado_recusado_pela_sefaz`, a SEFAZ recusou o certificado\nsem processar a nota (nenhuma NF-e foi criada lá): a Sudrel tenta de novo em\n`proxima_tentativa`, e a prontidão mostra o item `certificado_sefaz`. Com\n`envio_pausado`, a recusa se repetiu (3 vezes, por padrão) e a Sudrel parou de\ntentar (webhook `NFE_ENVIO_PAUSADO`): a nota volta sozinha quando o\ncertificado passar no teste da prontidão (um certificado novo, ou o mesmo uma\nhora depois).\n",
            "properties": {
              "motivo": {
                "type": "string",
                "enum": [
                  "certificado_recusado_pela_sefaz",
                  "envio_pausado",
                  "uf_indisponivel",
                  "falha_antes_do_envio"
                ]
              },
              "mensagem": {
                "type": "string"
              },
              "desde": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "proxima_tentativa": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "pausado_em": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "contingencia": {
            "type": "object",
            "nullable": true,
            "description": "A nota entrou em contingência (veja Contingência da NF-e). Nulo na emissão normal.",
            "properties": {
              "modo": {
                "type": "string",
                "enum": [
                  "svc_an",
                  "svc_rs",
                  "epec"
                ]
              },
              "tp_emis": {
                "type": "integer",
                "enum": [
                  4,
                  6,
                  7
                ]
              },
              "situacao": {
                "type": "string",
                "enum": [
                  "em_contingencia",
                  "autorizada_em_contingencia",
                  "epec_registrado",
                  "epec_prazo_proximo",
                  "epec_rejeitado",
                  "duplicata_cancelada",
                  "duplicata_nao_cancelada",
                  "duplicata_original_denegada"
                ]
              },
              "motivo": {
                "type": "string",
                "description": "A justificativa (xJust) impressa no DANFE."
              },
              "desde": {
                "type": "string",
                "format": "date-time"
              },
              "chave_original": {
                "type": "string",
                "description": "A chave tpEmis 1, que nunca foi transmitida."
              },
              "chave_original_transmitida": {
                "type": "boolean",
                "enum": [
                  false
                ]
              },
              "epec": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "protocolo": {
                    "type": "string"
                  },
                  "registrado_em": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "prazo_transmissao": {
                    "type": "string",
                    "format": "date-time",
                    "description": "168 horas depois do EPEC."
                  },
                  "correcao": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "reconciliacao": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "em": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "resultado": {
                    "type": "string",
                    "enum": [
                      "original_inexistente",
                      "duplicata_cancelada",
                      "duplicata_nao_cancelada",
                      "duplicata_original_denegada"
                    ]
                  }
                }
              }
            }
          },
          "confirmacao": {
            "type": "object",
            "nullable": true,
            "properties": {
              "motivo": {
                "type": "string"
              },
              "desde": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "mensagem": {
                "type": "string"
              },
              "correcao": {
                "type": "string"
              }
            }
          },
          "descarte": {
            "type": "object",
            "nullable": true,
            "properties": {
              "em": {
                "type": "string",
                "format": "date-time"
              },
              "automatico": {
                "type": "boolean"
              },
              "motivo": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "cancelamento": {
            "type": "object",
            "nullable": true,
            "properties": {
              "em": {
                "type": "string",
                "format": "date-time"
              },
              "protocolo": {
                "type": "string"
              },
              "justificativa": {
                "type": "string"
              }
            }
          },
          "cartas_correcao": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "sequencia": {
                  "type": "integer"
                },
                "texto": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "transmitindo",
                    "registrada",
                    "rejeitada"
                  ]
                },
                "protocolo": {
                  "type": "string",
                  "nullable": true
                },
                "sefaz": {
                  "type": "object",
                  "nullable": true,
                  "properties": {
                    "cstat": {
                      "type": "string"
                    },
                    "motivo": {
                      "type": "string"
                    }
                  }
                },
                "em": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          },
          "ajustes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "campo": {
                  "type": "string"
                },
                "acao": {
                  "type": "string",
                  "enum": [
                    "preenchido",
                    "derivado",
                    "exigido",
                    "omitido",
                    "calculado",
                    "divergente"
                  ]
                },
                "motivo": {
                  "type": "string"
                },
                "regra": {
                  "type": "string"
                },
                "valor": {
                  "description": "Modos calcular e conferir: o valor.",
                  "nullable": true
                },
                "versao": {
                  "type": "string",
                  "description": "Versão da regra, tabela ou calculadora."
                },
                "fonte": {
                  "type": "string",
                  "description": "Fonte legal do valor."
                }
              }
            }
          },
          "eventos": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "tipo": {
                  "type": "string"
                },
                "em": {
                  "type": "string",
                  "format": "date-time"
                },
                "detalhe": {
                  "type": "object"
                }
              }
            }
          },
          "regras_versao": {
            "type": "string"
          },
          "criada_em": {
            "type": "string",
            "format": "date-time"
          },
          "atualizada_em": {
            "type": "string",
            "format": "date-time"
          },
          "links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string"
              },
              "xml": {
                "type": "string"
              },
              "danfe": {
                "type": "string"
              }
            }
          }
        }
      },
      "NfeRecusa": {
        "type": "object",
        "nullable": true,
        "properties": {
          "codigo_oficial": {
            "type": "string",
            "description": "cStat da SEFAZ."
          },
          "mensagem": {
            "type": "string",
            "description": "xMotivo da SEFAZ."
          },
          "explicacao": {
            "type": "object",
            "nullable": true,
            "properties": {
              "codigo": {
                "type": "string"
              },
              "campo": {
                "type": "string",
                "nullable": true
              },
              "correcao": {
                "type": "string"
              }
            }
          }
        }
      },
      "NfePrevia": {
        "type": "object",
        "properties": {
          "valida": {
            "type": "boolean"
          },
          "empresa_id": {
            "type": "string",
            "nullable": true
          },
          "referencia": {
            "type": "string",
            "nullable": true
          },
          "modo": {
            "type": "string"
          },
          "serie": {
            "type": "integer",
            "nullable": true
          },
          "numero_previsto": {
            "type": "integer",
            "nullable": true
          },
          "chave_prevista": {
            "type": "string",
            "nullable": true
          },
          "totais": {
            "type": "object",
            "nullable": true,
            "properties": {
              "valor_produtos": {
                "type": "string"
              },
              "valor_nota": {
                "type": "string"
              }
            }
          },
          "xml": {
            "type": "string",
            "nullable": true,
            "description": "O XML que seria enviado, ainda sem assinatura."
          },
          "ajustes": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "erros": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ErroCampo"
            }
          },
          "prontidao": {
            "type": "object",
            "nullable": true
          },
          "fora_de_cobertura": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ForaDeCobertura"
            },
            "description": "Modos calcular e conferir."
          },
          "divergencias": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Modo conferir."
          }
        }
      },
      "ProntidaoNfe": {
        "type": "object",
        "properties": {
          "empresa_id": {
            "type": "string"
          },
          "situacao": {
            "type": "string",
            "enum": [
              "ok",
              "aviso",
              "bloqueio"
            ]
          },
          "itens": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "item": {
                  "type": "string",
                  "description": "Estável. Novos itens podem aparecer.",
                  "enum": [
                    "certificado",
                    "certificado_sefaz",
                    "endereco",
                    "regime_tributario",
                    "inscricao_estadual",
                    "cadastro_sefaz",
                    "habilitacao_nfe",
                    "escritorio_contabilidade",
                    "producao_liberada",
                    "caixa",
                    "csc",
                    "nfce_uf",
                    "nfce_producao"
                  ]
                },
                "situacao": {
                  "type": "string",
                  "enum": [
                    "ok",
                    "aviso",
                    "bloqueio"
                  ]
                },
                "mensagem": {
                  "type": "string"
                },
                "correcao": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          }
        }
      },
      "InutilizacaoNfe": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "empresa_id": {
            "type": "string"
          },
          "serie": {
            "type": "integer"
          },
          "numero_inicial": {
            "type": "integer"
          },
          "numero_final": {
            "type": "integer"
          },
          "justificativa": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "sefaz": {
            "type": "object",
            "nullable": true,
            "properties": {
              "cstat": {
                "type": "string"
              },
              "motivo": {
                "type": "string"
              }
            }
          },
          "protocolo": {
            "type": "string",
            "nullable": true
          },
          "notas": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ids das notas descartadas cujos números esta faixa consumiu."
          },
          "criada_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Problema": {
        "description": "Corpo de erro das rotas de emissão, lote, webhooks e eventos, com\n`Content-Type: application/problem+json`. Inspirado na RFC 9457, mas com\ncampos próprios: não há `title`, `status`, `detail` nem `instance`. O\nstatus HTTP está na resposta; programe em cima de `codigo`.\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/ErroCampo"
          },
          {
            "type": "object",
            "properties": {
              "requisicao_id": {
                "type": "string",
                "description": "Id desta requisição (o mesmo do cabeçalho `X-Request-Id`). Procure por ele em Integrações › Log da API."
              },
              "nfse_id": {
                "type": "string",
                "description": "Em `referencia_duplicada` (409), `nfse_rejeitada` e `falha_transmissao` (422): o id da nota."
              },
              "nfse": {
                "description": "Em `nfse_rejeitada` e `falha_transmissao` (422): a nota inteira, igual a `GET /v1/nfse/{id}`.",
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Nfse"
                  }
                ]
              },
              "nfe_id": {
                "type": "string",
                "description": "Em `referencia_duplicada` (409), `nfe_rejeitada`, `nfe_denegada`, `cancelamento_recusado` e `carta_correcao_recusada` (422): o id da NF-e."
              },
              "fora_de_cobertura": {
                "type": "array",
                "description": "Em `fora_de_cobertura` (422): o que o motor fiscal não calcula, com o motivo.",
                "items": {
                  "$ref": "#/components/schemas/ForaDeCobertura"
                }
              },
              "divergencias": {
                "type": "array",
                "description": "Em `conferencia_divergente` (422).",
                "items": {
                  "type": "object"
                }
              },
              "nfe": {
                "description": "Nos mesmos 422 da NF-e: a nota inteira, igual a `GET /v1/nfe/{id}`.",
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Nfe"
                  }
                ]
              },
              "erros": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ErroCampo"
                }
              },
              "itens": {
                "type": "array",
                "description": "Só em `empresa_nao_pronta` (412).",
                "items": {
                  "$ref": "#/components/schemas/ItemProntidao"
                }
              }
            }
          }
        ]
      },
      "Erro": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "integer"
          },
          "message": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          },
          "error": {
            "type": "string"
          }
        }
      },
      "Conta": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "nome": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "ATIVA",
              "SOMENTE_LEITURA"
            ]
          },
          "ambiente": {
            "$ref": "#/components/schemas/AmbienteChaveApi"
          },
          "criadaEm": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Plano": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "nome": {
            "type": "string"
          },
          "precoMensal": {
            "type": "string",
            "description": "Valor decimal em reais, como string (evita perda de precisão de ponto flutuante)."
          },
          "franquiaEventos": {
            "type": "integer"
          },
          "precoUnitarioExcedente": {
            "type": "string"
          },
          "percentualDescontoAnual": {
            "type": "string",
            "nullable": true
          },
          "produto": {
            "type": "string",
            "enum": [
              "RECEBIDAS",
              "EMISSAO"
            ]
          },
          "trial": {
            "type": "boolean"
          }
        }
      },
      "Ciclo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "ATIVO",
              "TOLERANCIA",
              "ENCERRADO"
            ]
          },
          "dataInicio": {
            "type": "string",
            "format": "date-time"
          },
          "dataFim": {
            "type": "string",
            "format": "date-time"
          },
          "plano": {
            "$ref": "#/components/schemas/Plano"
          }
        }
      },
      "Consumo": {
        "type": "object",
        "description": "Só o ciclo do produto **Recebidas**. O consumo da Emissão não aparece\naqui. Sem ciclo, a resposta traz só `temCicloAtivo: false`,\n`acessoProdutos` e `planoMinimoRecebidas`.\n",
        "properties": {
          "temCicloAtivo": {
            "type": "boolean"
          },
          "acessoProdutos": {
            "type": "object",
            "properties": {
              "recebidas": {
                "type": "boolean"
              },
              "emissao": {
                "type": "boolean"
              }
            }
          },
          "planoMinimoRecebidas": {
            "type": "object",
            "nullable": true,
            "description": "Se a conta precisa de um plano maior pelo número de CNPJs monitorados."
          },
          "ciclo": {
            "$ref": "#/components/schemas/Ciclo"
          },
          "franquiaEventos": {
            "type": "integer"
          },
          "eventosIncluidos": {
            "type": "integer"
          },
          "eventosExcedentes": {
            "type": "integer"
          },
          "documentosNoCiclo": {
            "type": "object",
            "description": "`eventosIncluidos + eventosExcedentes` separados em notas e eventos de nota (cancelamento, manifestação...).",
            "properties": {
              "notas": {
                "type": "integer"
              },
              "eventos": {
                "type": "integer"
              }
            }
          },
          "historicoAbatidoFranquia": {
            "type": "integer",
            "description": "Acordo comercial; só informativo."
          },
          "saldoExcedenteAberto": {
            "type": "number",
            "description": "Valor em reais do excedente ainda não pago neste ciclo."
          },
          "limiteExcedenteAberto": {
            "type": "number",
            "description": "A partir de quanto de excedente em aberto a conta é pausada automaticamente."
          },
          "porEmpresa": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "empresaId": {
                  "type": "string"
                },
                "quantidade": {
                  "type": "integer"
                }
              }
            }
          },
          "pausadaPorExcedente": {
            "type": "boolean"
          },
          "destravaDisponivel": {
            "type": "boolean"
          },
          "pacoteImportacao": {
            "type": "object",
            "nullable": true,
            "description": "Pacote de importação de histórico da conta, separado da franquia."
          }
        }
      },
      "AmbienteChaveApi": {
        "type": "string",
        "enum": [
          "SANDBOX",
          "PRODUCAO"
        ]
      },
      "AmbienteAdn": {
        "type": "string",
        "description": "Qual Ambiente de Dados Nacional (da Receita Federal) é consultado. HOMOLOGACAO nunca gera cobrança.",
        "enum": [
          "HOMOLOGACAO",
          "PRODUCAO"
        ]
      },
      "EscopoMonitoramento": {
        "type": "string",
        "description": "O que conta como visível/cobrável para esta empresa — todas as notas são sempre consultadas e guardadas, isso só afeta exibição e franquia.",
        "enum": [
          "RECEBIDAS",
          "EMITIDAS",
          "AMBAS"
        ]
      },
      "EstadoEmpresa": {
        "type": "string",
        "enum": [
          "DRAFT",
          "VALIDATING",
          "ANALISANDO_HISTORICO",
          "INITIAL_SYNC",
          "ACTIVE",
          "PAUSED_BY_USER",
          "PAUSED_CERTIFICATE",
          "PAUSED_BILLING",
          "ERROR",
          "REMOVAL_PENDING",
          "REMOVED"
        ]
      },
      "SituacaoNota": {
        "type": "string",
        "enum": [
          "AUTORIZADA",
          "CANCELADA",
          "SUBSTITUIDA"
        ]
      },
      "PapelNota": {
        "type": "string",
        "description": "RECEBIDA = a empresa é a tomadora do serviço; EMITIDA = a empresa é a prestadora. FORA_DE_ESCOPO existe no filtro, mas não aparece nas listas: é o documento em que a empresa não é nenhuma das duas partes, que também não conta na franquia.",
        "enum": [
          "RECEBIDA",
          "EMITIDA",
          "FORA_DE_ESCOPO"
        ]
      },
      "CriarEmpresaRequest": {
        "type": "object",
        "required": [
          "cnpj"
        ],
        "properties": {
          "cnpj": {
            "type": "string",
            "minLength": 11,
            "description": "Só dígitos."
          },
          "nomeExibicao": {
            "type": "string"
          },
          "nsuInicial": {
            "type": "integer",
            "minimum": 0,
            "description": "Avançado — de onde retomar a consulta ao ADN, se este CNPJ já era monitorado por outro sistema. Ausência = 0 (histórico completo)."
          }
        }
      },
      "Empresa": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "cnpj": {
            "type": "string"
          },
          "ambiente": {
            "$ref": "#/components/schemas/AmbienteChaveApi"
          },
          "ambienteAdn": {
            "$ref": "#/components/schemas/AmbienteAdn"
          },
          "escopoMonitoramento": {
            "$ref": "#/components/schemas/EscopoMonitoramento"
          },
          "nomeExibicao": {
            "type": "string",
            "nullable": true
          },
          "razaoSocial": {
            "type": "string",
            "nullable": true
          },
          "estado": {
            "$ref": "#/components/schemas/EstadoEmpresa"
          },
          "nsuInicial": {
            "type": "string"
          },
          "nsuUltimoConfirmado": {
            "type": "string",
            "nullable": true
          },
          "ultimaConsultaEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "monitorarDesde": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Só notas emitidas a partir desta data aparecem e são cobradas. Ausência (null) = sem corte, todo o histórico aparece."
          },
          "certificadoValidoAte": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "criadaEm": {
            "type": "string",
            "format": "date-time"
          },
          "atualizadaEm": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Prestador": {
        "type": "object",
        "properties": {
          "documento": {
            "type": "string"
          },
          "nome": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "NotaResumo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "tipoDocumento": {
            "$ref": "#/components/schemas/TipoDocumentoFiscal"
          },
          "numero": {
            "type": "string"
          },
          "nsu": {
            "type": "string",
            "nullable": true,
            "description": "Nulo quando o documento foi descoberto pela chave de acesso, sem NSU do ambiente nacional."
          },
          "chaveAcesso": {
            "type": "string"
          },
          "prestador": {
            "$ref": "#/components/schemas/Prestador"
          },
          "cnpjTomador": {
            "type": "string"
          },
          "papel": {
            "$ref": "#/components/schemas/PapelNota"
          },
          "valorServicos": {
            "type": "string"
          },
          "situacao": {
            "$ref": "#/components/schemas/SituacaoNota"
          },
          "dataEmissao": {
            "type": "string",
            "format": "date-time"
          },
          "recebidaEm": {
            "type": "string",
            "format": "date-time"
          },
          "quantidadeEventos": {
            "type": "integer"
          },
          "quantidadeManifestacoes": {
            "type": "integer"
          },
          "manifestacaoVigente": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TipoManifestacao"
              }
            ],
            "nullable": true,
            "description": "A manifestação mais recente registrada, que é a que vale perante a SEFAZ."
          }
        }
      },
      "TipoDocumentoFiscal": {
        "type": "string",
        "enum": [
          "NFSE",
          "NFE",
          "CTE"
        ]
      },
      "TipoManifestacao": {
        "type": "string",
        "description": "NF-e usa as quatro primeiras; CT-e, `PRESTACAO_SERVICO_DESACORDO`.",
        "enum": [
          "CIENCIA_OPERACAO",
          "CONFIRMACAO_OPERACAO",
          "DESCONHECIMENTO_OPERACAO",
          "OPERACAO_NAO_REALIZADA",
          "PRESTACAO_SERVICO_DESACORDO"
        ]
      },
      "Manifestacao": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "tipo": {
            "$ref": "#/components/schemas/TipoManifestacao"
          },
          "status": {
            "type": "string",
            "enum": [
              "ENVIADA",
              "REJEITADA"
            ]
          },
          "protocolo": {
            "type": "string",
            "nullable": true
          },
          "motivoRejeicao": {
            "type": "string",
            "nullable": true
          },
          "criadaEm": {
            "type": "string",
            "format": "date-time"
          },
          "temXmlEvento": {
            "type": "boolean",
            "description": "Se o XML do evento existe. O XML em si não vem nesta resposta."
          }
        }
      },
      "Evento": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "tipo": {
            "type": "string",
            "description": "Tipo do evento (cancelamento, substituição etc.) — string livre, o ADN pode introduzir tipos novos sem exigir mudança de contrato."
          },
          "sequencia": {
            "type": "integer"
          },
          "dataEvento": {
            "type": "string",
            "format": "date-time"
          },
          "recebidoEm": {
            "type": "string",
            "format": "date-time"
          },
          "nsu": {
            "type": "string"
          },
          "situacaoResultante": {
            "$ref": "#/components/schemas/SituacaoNota"
          },
          "xmlOriginal": {
            "type": "string"
          }
        }
      },
      "NotaDetalhe": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "empresaId": {
            "type": "string"
          },
          "tipoDocumento": {
            "$ref": "#/components/schemas/TipoDocumentoFiscal"
          },
          "chaveAcesso": {
            "type": "string"
          },
          "cnpjTomador": {
            "type": "string"
          },
          "papel": {
            "$ref": "#/components/schemas/PapelNota"
          },
          "prestador": {
            "$ref": "#/components/schemas/Prestador"
          },
          "numero": {
            "type": "string"
          },
          "serie": {
            "type": "string"
          },
          "dataEmissao": {
            "type": "string",
            "format": "date-time"
          },
          "municipio": {
            "type": "string",
            "nullable": true
          },
          "descricaoServico": {
            "type": "string",
            "nullable": true
          },
          "municipioEmitente": {
            "type": "string",
            "nullable": true,
            "description": "NF-e: cidade/UF do emitente, lido do XML."
          },
          "trajeto": {
            "type": "string",
            "nullable": true,
            "description": "CT-e: origem → destino da prestação."
          },
          "produtos": {
            "type": "array",
            "nullable": true,
            "description": "NF-e: itens da nota.",
            "items": {
              "type": "object",
              "properties": {
                "descricao": {
                  "type": "string"
                },
                "quantidade": {
                  "type": "string",
                  "nullable": true
                },
                "unidade": {
                  "type": "string",
                  "nullable": true
                },
                "valor": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          },
          "descricaoCarga": {
            "type": "string",
            "nullable": true,
            "description": "CT-e: produto predominante da carga (ou a descrição do serviço no CT-e OS)."
          },
          "valorServicos": {
            "type": "string"
          },
          "situacao": {
            "$ref": "#/components/schemas/SituacaoNota"
          },
          "nsu": {
            "type": "string",
            "nullable": true
          },
          "recebidaEm": {
            "type": "string",
            "format": "date-time"
          },
          "xmlOriginal": {
            "type": "string"
          },
          "eventos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Evento"
            }
          },
          "manifestacoes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Manifestacao"
            }
          }
        }
      }
    }
  },
  "x-tagGroups": [
    {
      "name": "Primeiros passos",
      "tags": [
        "Comece aqui",
        "Regras de integração",
        "Receitas"
      ]
    },
    {
      "name": "Conceitos",
      "tags": [
        "Idempotência",
        "Erros e status HTTP",
        "Estados da NFS-e",
        "Prontidão",
        "Paginação e limites"
      ]
    },
    {
      "name": "Emissão de NFS-e",
      "tags": [
        "Emissão de NFS-e",
        "Emissão em lote"
      ]
    },
    {
      "name": "Emissão de NF-e",
      "tags": [
        "Início rápido de NF-e",
        "Emissão de NF-e",
        "Produtos e motor fiscal",
        "NF-e pela planilha e em lote",
        "Contingência da NF-e"
      ]
    },
    {
      "name": "Emissão de NFC-e",
      "tags": [
        "Emissão de NFC-e"
      ]
    },
    {
      "name": "Documentos recebidos",
      "tags": [
        "Documentos"
      ]
    },
    {
      "name": "Cadastro",
      "tags": [
        "Conta",
        "Empresas"
      ]
    },
    {
      "name": "Notificações",
      "tags": [
        "Webhooks",
        "Eventos"
      ]
    },
    {
      "name": "Testes",
      "tags": [
        "Simulador de falhas"
      ]
    },
    {
      "name": "Ferramentas",
      "tags": [
        "SDKs",
        "OpenAPI e Postman",
        "IA e MCP"
      ]
    },
    {
      "name": "Ajuda",
      "tags": [
        "Problemas comuns",
        "Glossário",
        "Changelog"
      ]
    }
  ]
}