
# Conceitos

## A emissão é assíncrona

`POST /v1/nfe` e `POST /v1/nfse` não esperam a SEFAZ ou o Sistema Nacional. Eles validam o pedido, calculam os impostos, guardam a nota e respondem `202` com `"status": "queued"`. O envio acontece em segundo plano, com novas tentativas automáticas quando o órgão está fora do ar.

O resultado chega de duas formas:

- **webhook** (recomendado): `nfe.authorized`, `nfe.rejected`, `nfse.authorized`... Veja [Webhooks](../webhooks/);
- **consulta**: `GET /v1/nfe/{id}` ou `GET /v1/nfe?externalId=...`.

## Situações da nota

| Situação | O que significa | O que fazer |
|---|---|---|
| `queued`, `sending`, `pending` | Na fila ou em envio | Esperar |
| `unknown` | A resposta do órgão se perdeu; a emitza está conferindo se a nota foi registrada | Esperar. Nunca emita de novo com outro `externalId` |
| `authorized` | Autorizada, com valor fiscal (em produção) | Baixar o XML e o PDF |
| `rejected` | Recusada pelo órgão, com o motivo em `rejection` | Corrigir e reenviar com o **mesmo** `externalId` |
| `denied` | Uso denegado (NF-e): registrada, mas sem valor, por irregularidade do emitente ou do destinatário | Resolver a situação cadastral; o número fica consumido |
| `failed` | Parou sem resposta do órgão (ex.: certificado vencido) | Corrigir a causa e chamar `POST /v1/nfe/{id}/retry` |
| `cancelled` | Cancelada por evento | Nada |

Quando `attention` vem preenchido, a nota precisa de ação manual. O campo traz um código (por exemplo, `reconcile_exhausted`, quando a conferência com o órgão não fechou). Fale com o suporte da emitza informando o `id` da nota.

## Idempotência: o externalId

O `externalId` é o seu identificador do pedido, e é ele que impede nota em dobro:

- repetir o mesmo pedido com o mesmo `externalId` devolve a nota que já existe, com status `200`, sem emitir outra. Use isso à vontade quando a sua requisição cair no meio;
- enviar o mesmo `externalId` com **outro** conteúdo devolve `409`, exceto quando a nota foi rejeitada;
- nota `rejected`: reenvie o pedido corrigido com o mesmo `externalId`. Ela é reenviada com a mesma série e o mesmo número.

Use um `externalId` por documento fiscal, por exemplo o número do pedido ou da ordem de serviço.

O `externalId` é único **por empresa**: com várias empresas na conta (um escritório de contabilidade ou um ERP), o mesmo número de pedido em empresas diferentes gera notas diferentes. Para buscar uma nota pelo `externalId` (`GET /v1/nfe?externalId=...` ou `GET /v1/nfse?externalId=...`), informe também `companyId` quando o mesmo `externalId` existir em mais de uma empresa; sem ele, a resposta é `409`.

## Erros

Todo erro tem o mesmo formato:

```json
{
  "error": {
    "code": "validation_failed",
    "message": "Dados inválidos",
    "details": [{ "path": "items[0].ncm", "message": "deve ter 8 dígitos" }]
  }
}
```

| Status | `code` | Quando |
|---|---|---|
| 400 | `bad_request` | JSON malformado |
| 401 | `unauthorized` | Chave ausente, inválida ou no endereço errado |
| 404 | `not_found` | Recurso inexistente ou de outro cliente |
| 409 | `conflict` | `externalId` com outro conteúdo, nota em situação que não permite a ação |
| 422 | `validation_failed` e outros | Campos inválidos (veja `details`) ou regra de negócio: `series_missing`, `certificate_unavailable`, `sandbox_homologation_only`... |
| 429 | `rate_limited` | Limite de requisições; espere o tempo do cabeçalho `Retry-After` |
| 503 | `busy` | Serviço ocupado; tente de novo depois do `Retry-After` |

Campos desconhecidos são recusados: um erro de digitação aparece na hora, em vez de ser ignorado em silêncio.

Rejeição da SEFAZ não é erro HTTP: a nota é aceita (`202`) e depois fica `rejected`, com `rejection.cStat` e `rejection.reason`.

## Valores e formatos

- Decimais em texto, com ponto: `"1500.00"`, `"7.6"`. Nunca número JSON, para não perder centavos.
- Datas no formato `AAAA-MM-DD`; data e hora em ISO 8601.
- CNPJ, CEP e códigos aceitam pontuação, que é removida.

## Limites

- 20 requisições por segundo por cliente, com picos de até 40.
- Corpo de até 1 MB.
- Até 990 itens por NF-e.

## Uso do mês

`GET /v1/usage?month=AAAA-MM` devolve, por empresa, as notas autorizadas no mês (NF-e e NFS-e, em produção e em homologação) e as cotações de imposto, com o total da conta. É a base da cobrança: só as notas de produção contam. Escritórios e ERPs usam para repassar o custo a cada cliente. Sem `month`, vale o mês atual; a contagem é pela data da autorização, no horário de Brasília.

## Apagar o certificado ou a empresa (LGPD)

O certificado e os dados da empresa são apagados quando você pede:

| Pedido | Resposta | O que acontece |
|---|---|---|
| `DELETE /v1/companies/{id}/certificate` | `200`, com `certificate: null` | O certificado é apagado e a empresa para de emitir até receber outro (`PUT /v1/companies/{id}/certificate`). |
| `DELETE /v1/companies/{id}` | `202`, com `status: deleting` | A empresa some da API na hora (`404`) e nada novo é aceito para ela. Em seguida é apagada com tudo dela: certificado, NF-e e NFS-e com XMLs e DANFEs, eventos, inutilizações, classes de imposto e o histórico de webhooks. Não tem volta. |

**Trabalho em andamento.** Uma nota sendo emitida, ou na dúvida e sendo conferida com a SEFAZ ou a prefeitura, precisa do certificado. Nesse caso:

- apagar o certificado responde `409 company_busy`: espere os webhooks e repita;
- apagar a empresa aceita o pedido e espera esse trabalho terminar antes de apagar.

Notas paradas esperando uma decisão (`attention`) não impedem a exclusão. Repetir o `DELETE` de uma empresa que já está sendo apagada é seguro: a resposta é o mesmo `202`.

**Notas de produção.** Elas têm valor fiscal, e guardar os XMLs por 5 anos é obrigação do emitente. Por isso, `DELETE /v1/companies/{id}` responde `409 company_has_documents` quando há notas ou inutilizações de produção. Primeiro baixe os XMLs (NF-e: `GET /v1/nfe/export`, mês a mês; NFS-e: `GET /v1/nfse/{id}/xml`). Depois repita com `?deleteDocuments=true`. Empresas do sandbox e notas de homologação são apagadas direto. Se uma nota de produção surgir depois de um pedido sem `deleteDocuments` (emitida no mesmo instante), a exclusão é desfeita e a empresa volta.

**O que fica.** Só o registro de auditoria do pedido (com o id da empresa, sem os dados dela) e a contagem de notas do mês, usada na cobrança. O arquivo cifrado do certificado sai do cofre na hora; a cópia de segurança versionada expira em até 30 dias.

## Ambientes

Cada empresa tem um `environment`: `homologation` (testes, sem valor fiscal) ou `production`. O ambiente vem da chave: com a chave de teste (`fsk_test_`), a empresa fica sempre em homologação; com a chave de produção (`fsk_live_`), sempre em produção. O mesmo CNPJ pode estar nas duas contas sem conflito. As séries e a numeração são separadas por ambiente: nota de teste nunca consome número de produção.
