# API REST

Integre o seu sistema ao Nota4You: cadastros, prévia, emissão, consulta e arquivos da nota.

## Convenções

- Endereço base: `https://app-staging.nota4you.com.br/api/v1`. Formato: JSON.
- Nomes de campos e caminhos em `snake_case`.
- Datas em ISO 8601, valores em reais como texto decimal (`"1500.0"`).
- Respostas de erro em `application/problem+json`.
- Contrato OpenAPI 3.1 em [`https://staging.nota4you.com.br/openapi.json`](https://staging.nota4you.com.br/openapi.json): todas as operações aceitas com chave de API, com esquemas, escopos e erros. Use para gerar um cliente ou para dar a um agente.

## Autenticação

Crie a chave em Configurações > Chaves de API (proprietários e administradores). O token aparece uma vez só. Envie em todas as requisições:

```http
Authorization: Bearer <sua chave>
```

Teste a chave com `GET /api/v1/current_api_key`: ela devolve o nome, a conta, os escopos e a validade.

| Escopo | Permite |
| --- | --- |
| `taxpayers:read` | Ler empresas, serviços e clientes. |
| `taxpayers:write` | Criar e alterar empresas, serviços, clientes e séries. |
| `invoices:read` | Ler notas, eventos e arquivos. |
| `invoices:write` | Prévia, emissão, correção e reenvio. |
| `invoices:cancel` | Cancelar notas. Com `invoices:write`, substituir notas. |
| `webhooks:manage` | Gerenciar webhooks. |
| `mcp` | Usar o [servidor MCP](/docs/assistentes-de-ia). |

Uma chave também pode ficar limitada a algumas empresas. A chave nunca passa do papel de quem a criou: se essa pessoa sai da conta, a chave para de funcionar.

## Endpoints principais

| Método | Caminho | Uso |
| --- | --- | --- |
| GET, POST | `/taxpayers` | Listar e cadastrar empresas. |
| GET, PATCH | `/taxpayers/:id` | Ler e alterar uma empresa. |
| GET, POST, PATCH | `/taxpayers/:id/services` | Catálogo de serviços. |
| GET, POST, PATCH | `/taxpayers/:id/customers` | Clientes. |
| POST | `/taxpayers/:id/invoice_previews` | Validar e estimar tributos, sem emitir. |
| GET, POST | `/taxpayers/:id/invoices` | Listar e emitir notas. |
| GET, PATCH | `/invoices/:id` | Ler uma nota; corrigir uma nota rejeitada. |
| POST | `/invoices/:id/retransmission` | Reenviar uma nota rejeitada. |
| POST | `/invoices/:id/cancellation` | Cancelar uma nota autorizada (escopo `invoices:cancel`). |
| POST | `/invoices/:id/substitution` | Substituir uma nota autorizada (escopos `invoices:write` e `invoices:cancel`). |
| GET | `/invoices/:id/events` | Eventos da nota (cancelamento e cancelamento por substituição), com as mensagens da Sefin Nacional. |
| GET | `/invoices/:id/xml`, `/invoices/:id/danfse` | XML da NFS-e e DANFSe em PDF. |
| GET, POST, PATCH, DELETE | `/webhook_endpoints` | Webhooks. Veja [Webhooks](/docs/webhooks). |
| GET | `/reference/...` | Municípios, códigos de serviço, NBS, CEP e CNPJ. |

## Emissão

1. `POST /taxpayers/:id/invoice_previews` valida e estima os tributos.
2. `POST /taxpayers/:id/invoices` com o mesmo corpo e o cabeçalho `Idempotency-Key` responde `202 Accepted` com a nota em `queued`.
3. O resultado chega por [webhook](/docs/webhooks) (`invoice.authorized` ou `invoice.rejected`), ou consulte `GET /invoices/:id`.

## Cancelamento

1. `POST /invoices/:id/cancellation` com `{ "cancellation": { "reason_code": "1", "reason_text": "Serviço cobrado em dobro" } }`. Motivos: `1` erro na emissão, `2` serviço não prestado, `9` outros. A descrição tem de 15 a 255 caracteres.
2. A resposta é `202 Accepted` com o evento em `queued`. Não há como desfazer.
3. A Sefin Nacional registra o evento: a nota passa a `cancelled` e o webhook `invoice.cancelled` é enviado. Se a Sefin recusar (por exemplo, prazo vencido), o evento fica `rejected`, a nota continua `authorized` e o webhook é `invoice_event.rejected`.
4. Um segundo pedido responde `409` com `invoice_event_pending`. Depois de um cancelamento recusado, pode pedir de novo.

## Substituição

1. `POST /invoices/:id/substitution` com o cabeçalho `Idempotency-Key` e `{ "invoice": { "service_value": "1450.00" }, "substitution": { "reason_code": "99", "reason_text": "Valor do serviço errado" } }`. Os campos que você não mandar em `invoice` são copiados da nota original; a série pode mudar. Motivos: `01` desenquadramento do Simples Nacional, `02` enquadramento no Simples Nacional, `03` inclusão retroativa de imunidade ou isenção, `04` exclusão retroativa de imunidade ou isenção, `05` rejeição pelo tomador ou intermediário, `99` outros. A descrição é opcional, de 15 a 255 caracteres.
2. A resposta é `202 Accepted` com a nova nota em `queued`. Acompanhe como uma emissão.
3. Quando a Sefin Nacional autoriza a nova nota, a original passa a `substituted`, ganha o evento `105102` (cancelamento por substituição) e o webhook `invoice.substituted` é enviado. Se a nova nota for rejeitada, a original continua `authorized`.
4. Enquanto a nova nota está na fila ou em transmissão, outro pedido de substituição ou de cancelamento da original responde `409` com `invoice_event_pending`.

## Idempotência

Toda requisição `POST` que cria um registro fiscal exige o cabeçalho `Idempotency-Key` (por exemplo, um UUID). Repetir a chave devolve a primeira resposta, sem emitir de novo. A mesma chave com outro corpo responde `409` com `idempotency_key_reused`.

## Paginação

Listas são paginadas: 25 itens por página, com o parâmetro `page`. A resposta traz os cabeçalhos `Link` (`rel="next"`, `rel="prev"`) e `Total-Count`.

## Erros

```http
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json
```

```json
{
  "title": "Verifique os campos destacados.",
  "status": 422,
  "code": "validation_failed",
  "errors": [{ "field": "serviceValue", "code": "greater_than", "message": "deve ser maior que 0" }]
}
```

- `code` é estável: use-o no seu código, não o `title`.
- `errors[].field` vem em camelCase (`serviceValue`), para casar com formulários.
- Códigos comuns: `invalid_api_key`, `api_key_expired`, `insufficient_scope`, `not_found`, `validation_failed`, `idempotency_key_reused`, `rate_limited`.
- `429` traz `Retry-After`. Veja [Limites de uso](/docs/limites).
