Introdução
A API do EmiteHub emite documentos fiscais eletrônicos. Você envia um JSON no modelo canônico do documento; a plataforma valida, monta o XML no layout vigente, assina com o certificado do emitente, transmite à SEFAZ e devolve o resultado.
A versão 1 cobre MDF-e, CT-e, NF-e, NFC-e e NFS-e (padrão nacional), todos com o mesmo ciclo de vida, a mesma autenticação e os mesmos webhooks. Os exemplos desta página usam o MDF-e; os demais documentos seguem o mesmo padrão:
| Documento | Emitir | Arquivo PDF | Eventos |
|---|---|---|---|
| MDF-e (58) | POST /v1/mdfe | /damdfe | cancel, close, drivers, documents · GET /v1/mdfe/open |
| CT-e (57) | POST /v1/cte | /dacte | cancel, correction |
| NF-e (55) | POST /v1/nfe | /danfe | cancel, correction |
| NFC-e (65) | POST /v1/nfce | /danfe | cancel (CSC em PUT /v1/issuers/{id}/nfce-csc) |
| NFS-e | POST /v1/nfse | /danfse | cancel |
Para todos: GET /v1/{doc}/{id}, POST /v1/{doc}/{id}/refresh e GET /v1/{doc}/{id}/xml. Status dos serviços da SEFAZ em GET /v1/sefaz/status. Detalhes na referência completa.
- REST + JSON, UTF-8, datas ISO 8601 em UTC
- Campos sem valor vêm como
null - Novos campos podem aparecer na v1: ignore os que não conhecer
Ambientes
| Ambiente | URL base | Chave | Validade fiscal |
|---|---|---|---|
| Sandbox | https://sandbox.api.emitehub.com/v1 | emitehub_test_… | Não (homologação SEFAZ) |
| Produção | https://api.emitehub.com/v1 | emitehub_live_… | Sim |
Uma chave de teste nunca emite em produção.
Autenticação
Envie a chave no cabeçalho X-API-Key em toda requisição. A chave é exibida uma única vez na criação; guarde-a em cofre de segredos. Use-a apenas de servidor para servidor, nunca em navegador ou aplicativo.
curl "https://sandbox.api.emitehub.com/v1/issuers" \ -H "X-API-Key: $EMITEHUB_API_KEY"
Primeiro MDF-e
1. Cadastre o emitente e o certificado
POST /v1/issuers { "cnpj": "00000000000191", "legalName": "Transportes Exemplo Ltda", "stateRegistration": "123456789", "taxRegime": "3", "rntrc": "00000000", "address": { … } } PUT /v1/issuers/{issuerId}/certificate # multipart: file (.pfx) + password
2. Emita
POST /v1/mdfe X-API-Key: emitehub_test_… Idempotency-Key: 6f1c2e0a-0000-4000-8000-000000000001 { "issuerId": "iss_exemplo", "emitterType": "transport_provider", "transporterType": "etc", "ufStart": "SP", "ufEnd": "MG", "loadingCities": [{ "ibgeCode": "3550308", "name": "São Paulo" }], "vehicle": { "plate": "ABC1D23", "plateUf": "SP", "tareKg": 8000 }, "drivers": [{ "name": "Condutor Exemplo", "cpf": "00000000000" }], "unloadings": [{ "city": { "ibgeCode": "3170206", "name": "Uberlândia" }, "documents": [{ "type": "nfe", "accessKey": "3500…(44 dígitos)" }] }], "totals": { "cargoValue": 15000.00, "cargoWeight": 12000, "weightUnit": "kg" } } # resposta 202 { "id": "mdfe_exemplo", "status": "processing" }
Todos os campos, regras e tabelas estão no schema MdfeInput da referência. Antes de enviar, o EmiteHub valida o payload (chave de acesso com dígito verificador, CPF/CNPJ, placas, municípios IBGE, entre outros) e responde 422 com os campos com problema, sem consumir numeração.
3. Acompanhe
GET /v1/mdfe/{id} # status, chave de acesso, protocolo, eventos
Ciclo de vida
| Status | Significado |
|---|---|
processing | Recebido, em validação, assinatura ou transmissão |
authorized | Autorizado pela SEFAZ; XML e PDF disponíveis |
rejected | Rejeitado; veja rejection.sefazCode, message e hint |
denied | Denegado pela SEFAZ |
contingency | Emitido em contingência, aguardando transmissão |
closed · cancelled | MDF-e encerrado ou cancelado por evento |
Eventos do MDF-e: POST /mdfe/{id}/close, /cancel, /drivers, /documents. Novos status podem ser adicionados; trate valores desconhecidos de forma genérica.
Idempotência
Toda operação que emite ou altera um documento exige o cabeçalho Idempotency-Key (um UUID por operação). Repetir a requisição com a mesma chave e o mesmo corpo devolve o mesmo resultado, sem gerar outro número. Mesma chave com corpo diferente retorna 409.
Webhooks
Cadastre uma URL em POST /webhooks com os eventos desejados. O secret aparece só na criação.
| Evento | Quando |
|---|---|
mdfe.authorized | Documento autorizado |
mdfe.rejected | Documento rejeitado |
mdfe.closed · mdfe.cancelled | Evento autorizado |
certificate.expiring | Certificado perto de vencer |
Cada entrega traz o cabeçalho X-EmiteHub-Signature: sha256=<HMAC-SHA256 do corpo>. Valide antes de processar e responda 2xx em até 10 s; caso contrário, reenviamos com espera progressiva. Use o id do evento para deduplicar.
// Node.js
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers['x-emitehub-signature']));Arquivos (XML e PDF)
GET /mdfe/{id}/xml e /damdfe devolvem uma URL assinada e temporária (cerca de 1 hora) em url e expiresAt. Baixe o arquivo e guarde sua cópia; peça um novo link quando precisar.
Erros
{ "error": { "code": "VALIDATION_ERROR", "message": "Chave de acesso inválida",
"details": [{ "field": "unloadings[0].documents[0].accessKey", "issue": "dígito verificador incorreto" }] } }| HTTP | Quando | O que fazer |
|---|---|---|
| 400 | Requisição malformada | Corrija; repetir não resolve |
| 401 · 403 | Chave inválida, expirada ou IP não autorizado | Verifique a chave e as permissões |
| 404 | Recurso inexistente | Confira o id |
| 409 | Conflito (ex.: mesma Idempotency-Key com corpo diferente) | Reutilize o corpo original ou use outra operação |
| 422 | Regra fiscal ou de estado | Leia details e sefazCode |
| 429 | Limite excedido | Aguarde Retry-After |
| 5xx | Erro nosso | Tente de novo com espera progressiva e a mesma Idempotency-Key |
Decida pelo código HTTP e pelo error.code; não interprete o texto de message.
Limites
O limite de requisições por minuto depende do plano. As respostas trazem RateLimit-Limit, RateLimit-Remaining e RateLimit-Reset; ao exceder, a API responde 429 com Retry-After.
Paginação e sincronização
Listagens aceitam page, limit (até 100) e updatedSince (ISO 8601 UTC, inclusivo). Para manter uma cópia local, guarde o maior updatedAt e grave por id com upsert.