# Emitir a primeira nota

> Prévia: a API abre junto com o painel.

Em cinco minutos, no ambiente de teste: sem certificado digital e sem valor fiscal.

## 1. Pegue a chave de teste

Crie a conta e copie a chave `nfs_test_...` no painel. Deixe numa variável de ambiente:

```sh
export NFSEIA_CHAVE="nfs_test_sua_chave"
```

Confira se ela funciona e veja os padrões da nota da sua empresa (código de serviço, descrição,
impostos):

```sh
curl https://api.nfseia.com.br/v1/empresa \
  -H "Authorization: Bearer $NFSEIA_CHAVE"
```

## 2. Emita

O mínimo é a referência do pedido, o tomador e o valor. O que você não mandar de serviço e impostos
vem dos padrões da empresa. Se o tomador ainda não estiver salvo, mande também o nome.

```sh
curl -X POST https://api.nfseia.com.br/v1/notas \
  -H "Authorization: Bearer $NFSEIA_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7d4f8c2a-1b3e-4f6a-9c0d-2e5b8a1f3c7d" \
  -d '{
    "referencia_externa": "pedido-1042",
    "tomador": {
      "documento": "12345678000195",
      "nome": "Padaria Pão Quente Ltda",
      "email": "financeiro@paoquente.com.br"
    },
    "servico": { "descricao": "Manutenção do site, novembro de 2026" },
    "valores": { "valor_servico": "1500.00" }
  }'
```

Em Node (18 ou mais novo, sem biblioteca):

```js
import { randomUUID } from 'node:crypto';

const resposta = await fetch('https://api.nfseia.com.br/v1/notas', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.NFSEIA_CHAVE}`,
    'Content-Type': 'application/json',
    // Gere uma vez por tentativa e reutilize se precisar repetir a mesma chamada.
    'Idempotency-Key': randomUUID(),
  },
  body: JSON.stringify({
    referencia_externa: 'pedido-1042',
    tomador: {
      documento: '12345678000195',
      nome: 'Padaria Pão Quente Ltda',
      email: 'financeiro@paoquente.com.br',
    },
    servico: { descricao: 'Manutenção do site, novembro de 2026' },
    valores: { valor_servico: '1500.00' },
  }),
  signal: AbortSignal.timeout(35_000),
});

const corpo = await resposta.json();
if (resposta.status === 201 || resposta.status === 200) {
  console.log(`Nota ${corpo.numero} ${corpo.status}`, corpo.links.pdf);
} else if (resposta.status === 202) {
  console.log('Nota pendente; o webhook avisa quando sair.', corpo.id);
} else {
  console.error(corpo.erro.mensagem, corpo.erro.como_resolver, corpo.erro.detalhes);
}
```

Em Python (com `requests`):

```py
import os
import uuid

import requests

resposta = requests.post(
    "https://api.nfseia.com.br/v1/notas",
    headers={
        "Authorization": f"Bearer {os.environ['NFSEIA_CHAVE']}",
        # Gere uma vez por tentativa e reutilize se precisar repetir a mesma chamada.
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "referencia_externa": "pedido-1042",
        "tomador": {
            "documento": "12345678000195",
            "nome": "Padaria Pão Quente Ltda",
            "email": "financeiro@paoquente.com.br",
        },
        "servico": {"descricao": "Manutenção do site, novembro de 2026"},
        "valores": {"valor_servico": "1500.00"},
    },
    timeout=35,
)

corpo = resposta.json()
if resposta.status_code in (200, 201):
    print(f"Nota {corpo['numero']} {corpo['status']}", corpo["links"]["pdf"])
elif resposta.status_code == 202:
    print("Nota pendente; o webhook avisa quando sair.", corpo["id"])
else:
    print(corpo["erro"]["mensagem"], corpo["erro"]["como_resolver"], corpo["erro"]["detalhes"])
```

## 3. Entenda a resposta

| Status | O que aconteceu | O que fazer |
| --- | --- | --- |
| `201` | Nota autorizada. | Guarde `id`, `numero` e `chave_acesso`. |
| `200` | Já havia nota com essa `referencia_externa`. | Trate como sucesso: é a mesma nota. |
| `202` | Nota `pendente`, com o motivo em `pendencia.motivo` (por exemplo, a SEFIN não respondeu a tempo). | Espere o webhook `nota.pendente_resolvida` ou consulte depois. Não emita de novo com outra referência. |
| `400` | Dados recusados antes do envio. | Corrija os campos de `erro.detalhes`. |
| `422` | A SEFIN recusou a nota de forma definitiva. | Corrija conforme `erro.detalhes` e emita de novo com a mesma referência e uma `Idempotency-Key` nova. |
| `429` ou `5xx` | Limite ou falha temporária. | Repita com a mesma `Idempotency-Key`, depois do `Retry-After`. |

Os códigos e o formato dos erros estão em [Erros e limites](https://nfseia.com.br/docs/erros).

## 4. Teste os caminhos difíceis

No ambiente de teste, um marcador na descrição do serviço força o resultado:

- `[simular:rejeitada]`: a SEFIN simulada recusa a nota (`422 nota_rejeitada`).
- `[simular:pendente]`: a nota fica `pendente` (`202`) e vira autorizada em cerca de 1 minuto, com os
  eventos `nota.pendente_resolvida` e `nota.autorizada`.

Exemplo: `"descricao": "Manutenção do site [simular:pendente]"`.

## 5. Baixe o PDF e o XML

```sh
curl https://api.nfseia.com.br/v1/notas/nota_01JC8Z4M3QK7T2V9X5B6N1R0PD/pdf \
  -H "Authorization: Bearer $NFSEIA_CHAVE" -o nota.pdf
```

O XML oficial fica em `/xml`, guardado por 5 anos. No teste, o PDF sai com a marca "sem valor
fiscal".

## 6. Vá para a produção

1. Envie o certificado digital A1 (e-CNPJ) da empresa pelo link de envio do painel. O arquivo vai
   direto para o cofre; nem o painel nem a API veem o certificado aberto.
2. Libere a produção no painel e confirme pelo e-mail da empresa.
3. Crie a chave `nfs_live_...` e troque no seu sistema. O código é o mesmo.

O teste grátis vale 5 notas reais ou 7 dias, o que vier primeiro. O ambiente de teste continua de
graça depois.
