Guia de início rápido

    Configurar a conta e emitir a primeira nota fiscal, do certificado digital ao XML autorizado.

    Antes da primeira chamada

    1. 01

      Envie o certificado digital A1

      No portal, em Configurações, envie o arquivo .pfx e a senha. É o certificado que assina suas notas — sem ele a SEFAZ não aceita nada. O A3 (token/cartão) não serve para emissão em servidor.

      Configurações → Certificado digital

    2. 02

      Confira os dados fiscais da empresa

      CNPJ, inscrição estadual, regime tributário, endereço e o CSC (obrigatório só para NFC-e). A série e a numeração inicial também ficam aqui.

      Configurações → Dados fiscais

    3. 03

      Gere sua API Key

      É ela que autentica cada chamada. Aparece uma única vez na criação: guarde num cofre de segredos, nunca no código-fonte nem no front-end.

      API Key → Gerar nova chave

    Autenticação

    Toda chamada leva sua API Key. Aceitamos os dois formatos abaixo — use o que for mais natural no seu cliente HTTP.

    headers
    Authorization: Bearer nth_sua_chave_aqui
    # ou
    X-API-Key: nth_sua_chave_aqui

    A chave identifica a empresa, então não existe parâmetro de CNPJ nas rotas: a nota sai sempre pelo emitente dono da chave.

    Emitindo a primeira NF-e

    O corpo mínimo tem destinatário e itens. Os demais campos têm padrão: a natureza da operação vira “Venda de mercadoria”, o CFOP do item vira 5102 e a operação é de saída.

    cURL
    curl -X POST https://notahub.api.br/api/v1/nfe/emitir \
      -H "Authorization: Bearer nth_sua_chave_aqui" \
      -H "Content-Type: application/json" \
      -d '{
        "destinatario": {
          "cnpj": "12.345.678/0001-90",
          "nome": "Comércio Silva Ltda",
          "logradouro": "Rua das Flores",
          "numero": "100",
          "bairro": "Centro",
          "cidade": "São Paulo",
          "uf": "SP",
          "cep": "01001-000"
        },
        "itens": [
          {
            "descricao": "Teclado mecânico ABNT2",
            "quantidade": 2,
            "valor_unitario": 349.90,
            "ncm": "84716053",
            "cfop": "5102"
          }
        ]
      }'

    O que volta

    A chave de acesso tem 44 dígitos e identifica a nota na SEFAZ. O protocolo é o número da autorização. O PDF vem em base64 no campo pdf.

    200 OK
    {
      "success": true,
      "data": {
        "chave": "35260712345678000190550010000000123456789012",
        "numero": 123,
        "serie": 1,
        "protocolo": "135260000012345",
        "status": "autorizada",
        "ambiente": "homologacao",
        "pdf": "JVBERi0xLjQKJ…",
        "processing_time_ms": 1832,
        "urls": {
          "xml": "/api/v1/nota/35260712345678000190550010000000123456789012/xml",
          "pdf": "/api/v1/nota/35260712345678000190550010000000123456789012/pdf"
        },
        "uso": { "notasEmitidas": 1, "limiteNotas": 100, "notasRestantes": 99 }
      }
    }

    Nos seus termos

    Node.js

    emitir.js
    const resposta = await fetch("https://notahub.api.br/api/v1/nfe/emitir", {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${process.env.NOTAHUB_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ destinatario, itens }),
    });
    
    const { success, data, error } = await resposta.json();
    
    if (!success) {
      // error.code e error.message dizem o que a SEFAZ recusou
      throw new Error(`${error.code}: ${error.message}`);
    }
    
    console.log("chave:", data.chave, "protocolo:", data.protocolo);

    PHP

    emitir.php
    $ch = curl_init("https://notahub.api.br/api/v1/nfe/emitir");
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            "Authorization: Bearer " . getenv("NOTAHUB_API_KEY"),
            "Content-Type: application/json",
        ],
        CURLOPT_POSTFIELDS => json_encode([
            "destinatario" => $destinatario,
            "itens" => $itens,
        ]),
    ]);
    
    $resposta = json_decode(curl_exec($ch), true);
    
    if (!$resposta["success"]) {
        throw new RuntimeException($resposta["error"]["message"]);
    }
    
    echo $resposta["data"]["chave"];

    Guardando o XML

    A lei exige guardar o XML autorizado por 5 anos. Nós guardamos, mas o arquivo é seu: baixe e mantenha uma cópia no seu lado também.

    download
    curl -X POST https://notahub.api.br/api/v1/nota/{chave}/xml \
      -H "Authorization: Bearer nth_sua_chave_aqui" \
      -o nota.xml

    No plano Ilimitado dá para configurar o envio automático dos XMLs da competência fechada para o e-mail do seu contador.

    Indo para produção

    • Troque o ambiente nas configurações. A numeração de produção é independente da de homologação.
    • Configure um webhook para receber a mudança de status sem ficar consultando a API.
    • Trate a rejeição. A SEFAZ recusa por motivos corriqueiros (NCM inválido, IE do destinatário errada) e a mensagem vem no error.message.
    • Nunca reemita por timeout. Consulte a nota pela chave antes: pode ter sido autorizada e a resposta é que se perdeu.