Idempotência

Falhas de rede, timeouts e quedas de processo são inevitáveis. A Aeses suporta chaves de idempotência para que repetir um POST seja seguro — a mesma requisição lógica só tem efeito uma vez, independentemente de quantas vezes você refaça.

Enviando uma chave de idempotência

Adicione o header Idempotency-Key em qualquer POST. O valor pode ser qualquer string de até 255 caracteres; um UUID v4 é um bom padrão.

Requisição idempotente
curl https://api.aeses.io/v1/deposits \
-H "x-api-key: sk_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
  "asset": "USDT",
  "chain": "ethereum"
}'

A primeira resposta é armazenada por 24 horas. Requisições subsequentes com a mesma chave e o mesmo corpo retornam a resposta original — inclusive o status code original — sem executar a operação de novo.

Onde usar

Recomendamos fortemente enviar uma chave de idempotência em todo POST. Na prática é obrigatório para:

  • POST /v1/deposits — evita gerar múltiplos endereços em retentativas.
  • POST /v1/withdrawals — previne gasto duplo se seu cliente refizer a chamada.
  • POST /v1/charges — evita criar payment intents duplicados.
  • POST /v1/webhook-deliveries/:id/replay — o reenvio é naturalmente idempotente, mas a chave previne floods acidentais.

GET e DELETE são naturalmente idempotentes e não exigem chave.

Gerando chaves

Gere uma chave uma vez por operação lógica, antes da primeira tentativa. Persista-a junto à operação no seu banco e reutilize em cada retentativa até a operação ter sucesso. Padrão comum:

operation_id = uuid4()
save(state="pending", idempotency_key=operation_id)

while not done:
  try:
    response = api.create_deposit(..., idempotency_key=operation_id)
    save(state="confirmed", deposit_id=response.id)
    done = True
  except RetryableError:
    sleep(backoff())

Nunca gere uma chave nova dentro do loop de retry — isso anula o propósito.

Comportamento do replay

A resposta replicada é byte a byte idêntica à original, inclusive respostas de erro. Se a requisição original retornou 400 invalid_request_error, o mesmo 400 é replicado; nenhum estado de negócio muda.

O Request-Id original é preservado em replays para auditoria. A resposta HTTP inclui adicionalmente:

  • Idempotency-Replayed: true — presente quando a resposta veio do cache.

Conflitos

Se você reutilizar a mesma chave com um corpo de requisição diferente, a Aeses retorna 409 idempotency_key_reused:

Resposta de conflito
{
"error": {
  "type": "idempotency_error",
  "code": "idempotency_key_reused",
  "message": "Idempotency-Key already used with a different request payload.",
  "request_id": "req_01HXYZ..."
}
}

Isso normalmente indica um bug no cliente: a chave foi reutilizada para uma operação não relacionada. Gere uma chave nova para cada nova operação lógica.

TTL

Registros de idempotência expiram 24 horas após a requisição original. Depois disso, a mesma chave pode ser reutilizada para uma operação nova sem conflito. Se você refizer a chamada depois da janela de 24h, a requisição é processada como se fosse nova — desenhe suas retentativas para completarem bem dentro dessa janela.