Idempotência
Uma requisição pode se perder no caminho: tempo esgotado na rede, nova
tentativa automática do seu cliente, falha do servidor depois de gravar e
antes de responder. Sem idempotência, repetir um POST /v1/sales cria duas
vendas. O cabeçalho Idempotency-Key resolve isso: a Ligga API guarda a
resposta da primeira chamada e devolve a mesma resposta nas repetições.
Como funciona
Seção intitulada “Como funciona”-
Gere um identificador único para a operação, de 1 a 255 caracteres. UUID v4 ou ULID são boas escolhas.
-
Envie esse identificador no cabeçalho
Idempotency-Keyda requisição. -
A API processa a primeira chamada e guarda a resposta por 24 horas, junto com a assinatura da requisição.
-
Qualquer repetição com a mesma chave, dentro da janela, devolve a resposta guardada sem reprocessar nada. A resposta repetida carrega o cabeçalho
Idempotent-Replay: true.
curl -X POST "$LIGGA_BASE/v1/sales" \ -H "Authorization: Bearer $LIGGA_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "c06d8705-f091-46e1-81bb-4a2cec656694", "transaction_type": "sale", "sale_date": "2026-05-18", "items": [] }'Onde a chave tem efeito
Seção intitulada “Onde a chave tem efeito”O cabeçalho é lido apenas em POST. Em GET, PATCH e DELETE ele é
ignorado, porque essas operações já são idempotentes: repetir a mesma
atualização parcial ou a mesma desativação leva ao mesmo estado final.
| Operação | Envie Idempotency-Key |
|---|---|
POST /v1/sales | Sempre. Uma venda duplicada corrompe o financeiro da conta |
POST /v1/customers | Sempre. Sem ela, uma nova tentativa cria o cliente duas vezes |
POST /v1/expenses | Sempre |
PATCH /v1/customers/{id} | Não. O cabeçalho é ignorado |
DELETE /v1/customers/{id} | Não. O cabeçalho é ignorado |
GET /v1/customers | Não. Leitura não tem efeito colateral |
Gerando a chave
Seção intitulada “Gerando a chave”import { randomUUID } from 'node:crypto';
const idempotencyKey = randomUUID();import uuid
idempotency_key = str(uuid.uuid4())$idempotencyKey = bin2hex(random_bytes(16));Não derive a chave do corpo da requisição, por exemplo com um hash do JSON. Duas vendas legitimamente idênticas no mesmo dia produziriam a mesma chave, e a segunda voltaria como repetição da primeira em vez de ser criada.
Comportamento ao reusar uma chave
Seção intitulada “Comportamento ao reusar uma chave”| Situação | Resposta |
|---|---|
| Mesma chave, mesma requisição, dentro de 24 horas | A resposta original, com Idempotent-Replay: true |
| Mesma chave, corpo diferente | 409 com type idempotency_conflict |
| Mesma chave, outro método ou outro caminho | 409 com type idempotency_conflict |
| Mesma chave, mais de 24 horas depois | Tratada como requisição nova |
| Chave com mais de 255 caracteres | 422 com type validation |
O 409 sinaliza um defeito no cliente: uma chave que deveria identificar uma
operação está sendo reaproveitada em outra. Gere uma chave nova em vez de
repetir a chamada.
Escopo da chave
Seção intitulada “Escopo da chave”A chave é guardada por chave de API. A assinatura comparada nas repetições cobre o método, o caminho e o corpo da requisição.
Duas chaves de API diferentes podem usar o mesmo valor de Idempotency-Key
sem interferência: são operações independentes. Já a mesma chave de API
reaproveitando o valor em outro endpoint recebe 409, porque a assinatura não
bate com a guardada.
Erros comuns
Seção intitulada “Erros comuns”Perder o cabeçalho na nova tentativa. Se o seu cliente HTTP repete a requisição sozinho e monta os cabeçalhos de novo a cada tentativa, a garantia some. Confira a configuração da camada de repetição antes de confiar nela.
Gerar a chave dentro do laço. A chave precisa ser criada antes da primeira tentativa e permanecer a mesma em todas elas.
// Errado: cada tentativa vira uma operação novafor (let i = 0; i < 3; i++) { await fetch(url, { headers: { 'Idempotency-Key': randomUUID() } });}
// Certo: uma chave para a operação inteiraconst key = randomUUID();for (let i = 0; i < 3; i++) { await fetch(url, { headers: { 'Idempotency-Key': key } });}Guardar a chave só na memória do processo. Em um processo que pode reiniciar entre a tentativa e a repetição, grave a chave junto com o registro de origem, para reencontrá-la depois.
Veja também
Seção intitulada “Veja também”- Erros — o corpo do
409e o catálogo completo - Limites de requisições — como espaçar novas tentativas
- Vendas (sales) — o
POSTque mais precisa de idempotência - Criar venda com itens — a receita completa