> ## Documentation Index
> Fetch the complete documentation index at: https://docs.engineapi.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Primeiros passos

> Do zero até a primeira nota emitida em homologação.

Siga os 4 passos abaixo. O acesso é por **pedido revisado** (sem cartão, sem
agente comercial); empresa, certificado e emissão são self-service assim que
seu acesso é liberado.

<Info>
  Todo emissor nasce em **homologação** (SEFAZ de teste, sem validade fiscal). Não
  existe um campo `environment` que você define no cadastro. Ver [Sandbox](/guides/sandbox)
  para o que isso significa na prática e como ir pra produção.
</Info>

<Info>
  **Antes de integrar o cenário do seu cliente:** confira se o regime tributário e a
  operação dele (ST, DIFAL, exportação, transporte...) já emitem hoje em [Cobertura
  Fiscal](/cobertura), documento × regime × cenário, com o erro exato onde não emite.
</Info>

***

<Steps>
  <Step title="Peça acesso e gere sua API Key">
    `POST /v1/auth/register` **não cria conta na hora**: grava um pedido de acesso
    antecipado e responde `202`. Nosso time revisa e, se liberar, você recebe um
    e-mail de convite para criar sua senha: aí sim nasce seu partner (a software
    house), com o plano Dev (R\$0) já ativo.

    <Tabs>
      <Tab title="cURL">
        ```bash theme={null}
        curl -X POST https://api.engineapi.com.br/v1/auth/register \
          -H "Content-Type: application/json" \
          -d '{
            "companyName": "Minha Software House Ltda",
            "name": "Dev Exemplo",
            "email": "dev@minhaempresa.com",
            "whatsapp": "11988887777",
            "emits": "NFe e NFCe para os clientes da minha plataforma",
            "volumePerMonth": "500",
            "erpStack": "Node + Postgres"
          }'
        ```
      </Tab>

      <Tab title="Node.js">
        ```typescript theme={null}
        const resp = await fetch('https://api.engineapi.com.br/v1/auth/register', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            companyName: 'Minha Software House Ltda',
            name: 'Dev Exemplo',
            email: 'dev@minhaempresa.com',
            whatsapp: '11988887777',
            emits: 'NFe e NFCe para os clientes da minha plataforma',
            volumePerMonth: '500',
            erpStack: 'Node + Postgres',
          }),
        });

        const { data } = await resp.json();
        console.log(data.message); // "Pedido de acesso recebido. ..."
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={null}
        import httpx

        resp = httpx.post('https://api.engineapi.com.br/v1/auth/register', json={
            'companyName': 'Minha Software House Ltda',
            'name': 'Dev Exemplo',
            'email': 'dev@minhaempresa.com',
            'whatsapp': '11988887777',
            'emits': 'NFe e NFCe para os clientes da minha plataforma',
            'volumePerMonth': '500',
            'erpStack': 'Node + Postgres',
        })

        print(resp.json()['data']['message'])
        ```
      </Tab>
    </Tabs>

    <Note>
      `whatsapp` exige DDD completo: 10 dígitos (fixo) ou 11 (celular, com o nono
      dígito). A validação ignora máscara, aceitando tanto dígitos crus
      (`11988887777`) quanto formatado (`(11) 98888-7777`), mas rejeita telefone
      incompleto (ex.: `11`).
    </Note>

    ```json Resposta de sucesso (202) theme={null}
    {
      "data": {
        "message": "Pedido de acesso recebido. Nossa equipe vai analisar e entrar em contato em breve.",
        "requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      },
      "meta": {
        "requestId": "req_abc123",
        "timestamp": "2026-07-06T12:00:00.000Z"
      }
    }
    ```

    <Info>
      **Liberado?** O e-mail de convite traz um link para criar a senha
      (`POST /v1/invite/accept`). Depois de entrar no [dashboard](https://app.engineapi.com.br),
      gere sua `ek_test_` em **Configurações → API Keys** (ou via
      `POST /v1/auth/api-keys/test/regenerate`, autenticado). Ela só aparece **uma vez**:
      guarde-a. Nenhum caminho de acesso antecipado emite `ek_live_`: a key de produção
      exige assinatura de plano pago, ver [Autenticação](/authentication).
    </Info>
  </Step>

  <Step title="Cadastre uma empresa emissora">
    Registre o CNPJ que vai emitir os documentos fiscais. A empresa nasce em homologação;
    guarde o `id` retornado: é o `issuerId` usado para escolher o emissor na emissão (opcional
    com um único emissor, obrigatório a partir do segundo).

    <Tabs>
      <Tab title="cURL">
        ```bash theme={null}
        curl -X POST https://api.engineapi.com.br/v1/companies \
          -H "x-api-key: ek_test_SUA_API_KEY" \
          -H "Content-Type: application/json" \
          -d '{
            "cnpj": "11222333000181",
            "name": "Empresa Exemplo Ltda",
            "tradeName": "Exemplo",
            "ie": "123456789",
            "crt": 1,
            "cep": "74063010",
            "address": "Rua Exemplo",
            "number": "100",
            "neighborhood": "Centro",
            "city": "Goiânia",
            "state": "GO",
            "ibgeCode": "5208707"
          }'
        ```
      </Tab>

      <Tab title="Node.js">
        ```typescript theme={null}
        const resp = await fetch('https://api.engineapi.com.br/v1/companies', {
          method: 'POST',
          headers: {
            'x-api-key': apiKey,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            cnpj: '11222333000181',
            name: 'Empresa Exemplo Ltda',
            tradeName: 'Exemplo',
            ie: '123456789',
            crt: 1, // 1=Simples Nacional, 3=Regime Normal (ver /conceitos/regimes-tributarios)
            cep: '74063010',
            address: 'Rua Exemplo',
            number: '100',
            neighborhood: 'Centro',
            city: 'Goiânia',
            state: 'GO',
            ibgeCode: '5208707',
          }),
        });

        const { data } = await resp.json();
        const issuerId = data.id;
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={null}
        resp = httpx.post('https://api.engineapi.com.br/v1/companies',
            headers={'x-api-key': api_key},
            json={
                'cnpj': '11222333000181',
                'name': 'Empresa Exemplo Ltda',
                'tradeName': 'Exemplo',
                'ie': '123456789',
                'crt': 1,
                'cep': '74063010',
                'address': 'Rua Exemplo',
                'number': '100',
                'neighborhood': 'Centro',
                'city': 'Goiânia',
                'state': 'GO',
                'ibgeCode': '5208707',
            },
        )

        issuer_id = resp.json()['data']['id']
        ```
      </Tab>
    </Tabs>

    <Warning>
      O payload usa `cep`/`address`/`number`/`neighborhood`/`city`/`state`/`ibgeCode` em campos
      soltos na raiz (não um objeto `address.{street,district,cityCode,zipCode}`), e `crt` (não
      `taxRegime`). Não existe campo `environment`, todo emissor nasce em homologação, ver
      [Sandbox](/guides/sandbox).
    </Warning>
  </Step>

  <Step title="Faça upload do certificado digital">
    Envie o certificado `.pfx` (A1) da empresa emissora. Ele será criptografado e armazenado com segurança.

    <Tabs>
      <Tab title="cURL">
        ```bash theme={null}
        curl -X POST https://api.engineapi.com.br/v1/companies/ISSUER_ID/certificate \
          -H "x-api-key: ek_test_SUA_API_KEY" \
          -F "file=@certificado.pfx" \
          -F "password=senhaDoCertificado"
        ```
      </Tab>

      <Tab title="Node.js">
        ```typescript theme={null}
        import { readFileSync } from 'fs';

        const form = new FormData();
        form.append('file', new Blob([readFileSync('certificado.pfx')]));
        form.append('password', 'senhaDoCertificado');

        await fetch(`https://api.engineapi.com.br/v1/companies/${issuerId}/certificate`, {
          method: 'POST',
          headers: { 'x-api-key': apiKey },
          body: form,
        });
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={null}
        with open('certificado.pfx', 'rb') as f:
            resp = httpx.post(
                f'https://api.engineapi.com.br/v1/companies/{issuer_id}/certificate',
                headers={'x-api-key': api_key},
                files={'file': ('cert.pfx', f, 'application/x-pkcs12')},
                data={'password': 'senhaDoCertificado'},
            )
        ```
      </Tab>
    </Tabs>

    <Warning>
      O campo multipart é **`file`**, não `certificate`.
    </Warning>

    <Info>
      Não tem certificado digital para testes? Em homologação, você pode usar um certificado de teste emitido por qualquer AC (Autoridade Certificadora) habilitada. Veja nosso [guia de certificados](/guides/certificates).
    </Info>
  </Step>

  <Step title="Emita sua primeira NF-e">
    Com a empresa e o certificado configurados, emita a nota.

    <Info>
      **Quais campos enviar?** O exemplo abaixo cobre o mínimo. A lista **completa** de
      campos de emissão, navegável por grupo (Identificação, Destinatário, Itens,
      Impostos, Transporte, Pagamento...), gerada direto do contrato real, está no
      [**Catálogo de campos: NF-e**](/api-reference/campos-nfe). Emitindo NFC-e ou NFS-e?
      Veja os catálogos de [NFC-e](/api-reference/campos-nfce) e [NFS-e](/api-reference/campos-nfse).
    </Info>

    <Tabs>
      <Tab title="cURL">
        ```bash theme={null}
        curl -X POST https://api.engineapi.com.br/v1/nfe \
          -H "x-api-key: ek_test_SUA_API_KEY" \
          -H "Content-Type: application/json" \
          -d '{
            "naturezaOperacao": "VENDA DE MERCADORIA",
            "idDest": 1,
            "indFinal": 1,
            "destinatario": {
              "cnpjCpf": "99888777000100",
              "nome": "Cliente Exemplo SA",
              "endereco": {
                "logradouro": "Av Goiás", "numero": "500",
                "bairro": "Centro", "codigoMunicipio": "5208707",
                "municipio": "Goiânia", "uf": "GO", "cep": "74063010"
              },
              "indicadorIE": 9
            },
            "items": [{
              "codigo": "PROD001",
              "descricao": "Produto Teste",
              "ncm": "84713012",
              "cfop": "5102",
              "unidade": "UN",
              "quantidade": 2,
              "valorUnitario": 150.00,
              "icms": { "origem": 0, "csosn": "400" }
            }],
            "pagamentos": [{ "forma": "01", "valor": 300.00 }]
          }'
        ```
      </Tab>

      <Tab title="Node.js">
        ```typescript theme={null}
        const resp = await fetch('https://api.engineapi.com.br/v1/nfe', {
          method: 'POST',
          headers: {
            'x-api-key': apiKey,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            naturezaOperacao: 'VENDA DE MERCADORIA',
            idDest: 1,
            indFinal: 1,
            destinatario: {
              cnpjCpf: '99888777000100',
              nome: 'Cliente Exemplo SA',
              endereco: {
                logradouro: 'Av Goiás', numero: '500',
                bairro: 'Centro', codigoMunicipio: '5208707',
                municipio: 'Goiânia', uf: 'GO', cep: '74063010',
              },
              indicadorIE: 9,
            },
            items: [{
              codigo: 'PROD001', descricao: 'Produto Teste',
              ncm: '84713012', cfop: '5102', unidade: 'UN',
              quantidade: 2, valorUnitario: 150.00,
              icms: { origem: 0, csosn: '400' },
            }],
            pagamentos: [{ forma: '01', valor: 300.00 }],
          }),
        });

        const { data } = await resp.json();
        console.log('NFe autorizada:', data.accessKey, data.status);
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={null}
        resp = httpx.post('https://api.engineapi.com.br/v1/nfe',
            headers={'x-api-key': api_key},
            json={
                'naturezaOperacao': 'VENDA DE MERCADORIA',
                'idDest': 1,
                'indFinal': 1,
                'destinatario': {
                    'cnpjCpf': '99888777000100',
                    'nome': 'Cliente Exemplo SA',
                    'endereco': {
                        'logradouro': 'Av Goiás', 'numero': '500',
                        'bairro': 'Centro', 'codigoMunicipio': '5208707',
                        'municipio': 'Goiânia', 'uf': 'GO', 'cep': '74063010',
                    },
                    'indicadorIE': 9,
                },
                'items': [{
                    'codigo': 'PROD001', 'descricao': 'Produto Teste',
                    'ncm': '84713012', 'cfop': '5102', 'unidade': 'UN',
                    'quantidade': 2, 'valorUnitario': 150.00,
                    'icms': {'origem': 0, 'csosn': '400'},
                }],
                'pagamentos': [{'forma': '01', 'valor': 300.00}],
            },
        )

        data = resp.json()['data']
        print(f"NFe autorizada: {data['accessKey']}")
        ```
      </Tab>
    </Tabs>

    ```json Resposta de sucesso theme={null}
    {
      "data": {
        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "status": "AUTHORIZED",
        "accessKey": "35260211222333000181550010000000011000000019",
        "protocol": "135260000001234",
        "number": 1,
        "series": 1,
        "model": "55",
        "amount": "300",
        "destCNPJ": "99888777000100",
        "destName": "Cliente Exemplo SA",
        "createdAt": "2026-07-06T12:00:00.000Z",
        "updatedAt": "2026-07-06T12:00:01.000Z",
        "downloads": {
          "xml": "/v1/nfe/xml/35260211222333000181550010000000011000000019",
          "pdf": "/v1/nfe/pdf/35260211222333000181550010000000011000000019"
        }
      },
      "meta": {
        "requestId": "req_abc123",
        "timestamp": "2026-07-06T12:00:00.000Z"
      }
    }
    ```

    <Warning>
      `issuerId` (UUID) é aceito na RAIZ do payload de NF-e/NFC-e/NFS-e: opcional se você tem um único
      emissor (a API usa o seu emissor), obrigatório a partir do segundo emissor (sem ele, `400`).
      Não existe `itens`/`pagamento` singular/`cnpj` separados: os nomes reais são
      `items`/`pagamentos[]`/`cnpjCpf`. Ver [Autenticação](/authentication#multi-tenancy) e
      [Primeira Emissão](/guides/first-emission) para o contrato completo.
    </Warning>

    <Warning>
      A resposta **não** tem `xml`/`xmlPath`/`pdfPath`/`invoiceId`/`message`: esses campos da
      versão antiga da doc nunca existiram no shape real (ou eram caminho de arquivo interno).
      `status` é `"AUTHORIZED"` (inglês, mesmo valor usado em `GET /v1/nfe/{id}` e no webhook
      `invoice.authorized`), `amount` é uma **string decimal** (`"300"`, sem zeros à direita, não `number`, evita
      imprecisão de ponto flutuante em dinheiro), e `downloads.xml`/`downloads.pdf` são os
      caminhos para baixar o XML/PDF (`GET /v1/nfe/xml/{accessKey}`, `GET /v1/nfe/pdf/{accessKey}`).
    </Warning>

    <Check>
      Sua primeira nota fiscal foi emitida e autorizada pelo SEFAZ de homologação.
    </Check>
  </Step>
</Steps>

***

## Próximos passos

<CardGroup cols={3}>
  <Card title="Catálogo de campos" icon="list" href="/api-reference/campos-nfe">
    Todo campo de NF-e/NFC-e/NFS-e, navegável por grupo, gerado do contrato real
  </Card>

  <Card title="Autenticação" icon="lock" href="/authentication">
    JWT, API Keys e multi-tenancy explicados
  </Card>

  <Card title="Primeira Emissão" icon="file-invoice" href="/guides/first-emission">
    Todos os campos obrigatórios detalhados
  </Card>

  <Card title="Webhooks" icon="bell" href="/guides/webhooks">
    Notificações em tempo real de cada evento
  </Card>
</CardGroup>
