Skip to Content
GuiasIdempotency-Key

Idempotency-Key

O cenário que tira o sono em fiscal: timeout no meio do request. Você manda POST /v1/nfce, network cai, retry — agora pode ter emitido duas notas pro mesmo pedido.

A solução Stripe-style: você manda um identificador único do seu lado no header Idempotency-Key. Se o gateway já viu essa chave em < 24h, devolve a mesma resposta que devolveu antes — sem reprocessar nada.

Como usar

curl -X POST https://api.zfiscoo.zek.app.br/v1/nfce \ -H "Authorization: Bearer fk_live_..." \ -H "Idempotency-Key: pedido-2026-001" \ -d '{ ... }'

Primeira chamada: processa normal. Retorna 201 Created (ou 202 Accepted). Segunda chamada (mesma key, mesmo body): devolve a mesma resposta + header Idempotency-Replay: true.

Em que endpoints

Em todo POST/PUT/PATCH mutativo (17 endpoints). Os principais:

  • POST /v1/nfce, POST /v1/nfe, POST /v1/nfse
  • POST /v1/nfce/:id/cancel, POST /v1/nfe/:id/cancel, POST /v1/nfse/:id/cancel
  • POST /v1/issuers, POST /v1/issuers/:id/csc, POST /v1/issuers/:id/inutilization
  • POST /v1/webhooks, POST /v1/applications (rotação de API key)

O que conta como “mesma chave”

Comparação tripla:

  1. Idempotency-Key (header)
  2. Body hash (SHA-256 do JSON do request)
  3. Path (rota HTTP)

Se você reenviar a mesma key com body diferente, recebe 422 idempotency_conflict:

{ "error": "idempotency_conflict", "message": "Idempotency-Key 'pedido-001' já foi usado neste endpoint com body diferente. Use uma nova chave ou mantenha o body idêntico." }

Isso impede bug clássico de “reusar chave por engano com payload novo” — onde o cliente pensa que tá emitindo nota nova mas o gateway devolve a antiga.

TTL

Chaves expiram após 24h. Depois disso, a mesma chave reativa um novo processamento.

Boas práticas de chave

// UUID por operação de negócio (não por request HTTP) const idemKey = `nfce:${pedidoId}`; // Ou hash determinístico de campos imutáveis const idemKey = crypto.createHash('sha256') .update(`${userId}:${pedidoId}:${amount}`) .digest('hex') .slice(0, 32); // UUID v4 random por intenção de criar nota const idemKey = crypto.randomUUID();

Detectando replay no client

O header de resposta indica:

HTTP/1.1 201 Created Idempotency-Replay: true Content-Type: application/json { "id": "nfce_...", "status": "processing" }

Útil pra logar / contar quantos retries seu sistema teve.

Não precisa usar Idempotency-Key em GET / DELETE — esses são naturalmente idempotentes pela spec HTTP. O gateway ignora o header se você mandar em GET.

Limite de tamanho

A chave precisa ter entre 8 e 256 caracteres. Recomendamos UUID v4 (36 chars) ou hash SHA-256 truncado (32 chars).