Idempotência
Torne seus POSTs e PATCHes seguros para retentativas. Sem usuários duplicados, sem cobrança em dobro, mesmo quando a rede cai no meio da chamada.
Uma chave de idempotência identifica de forma única uma requisição lógica, permitindo que a mesma operação seja retentada com segurança. Se a rede cai no meio de um POST /v1/quotes/:id/accept e você não sabe se a transação foi criada, retente com a mesma chave: a BlendFi devolve a mesma resposta em vez de criar uma segunda transação. Sem duplicatas, sem cobrança em dobro.
Todo POST e PATCH na API da BlendFi exige o cabeçalho Idempotency-Key. Esta página mostra o contrato e como usar.
Em três regras
Uma chave por operação lógica
Gere um UUID novo por intenção (uma cotação, uma criação de usuário, uma transação). Reaproveite a mesma chave nas retentativas dessa intenção.
Mesma chave nas retentativas, mesma resposta
Mesma chave + mesmo corpo retorna a resposta original, mesmo status, mesmo JSON. A operação nunca é executada duas vezes.
Corpo diferente com a mesma chave é rejeitado
Se você reaproveitar uma chave para uma requisição diferente sem querer, recebe `409 idempotency_key_reused`. Protege contra os seus próprios bugs.
Como funciona
1. Gere uma chave por intenção
Crie uma string única antes de enviar a requisição. UUID v4 é o formato recomendado; qualquer string aleatória e imprevisível serve.
import { randomUUID } from "node:crypto";
const idempotencyKey = randomUUID();
// "0196c5d9-2e34-7c24-a47e-a0e1f89bb8a9"A chave representa uma operação lógica, não uma tentativa de rede. Se precisar tentar de novo, reaproveite a mesma chave.
2. Envie a chave em todo POST e PATCH
Adicione o cabeçalho Idempotency-Key em toda requisição que escreve dados:
curl -X POST $BLENDFI_BASE/v1/quotes/$QUOTE_ID/accept \
-H "Authorization: Bearer $BLENDFI_KEY" \
-H "Idempotency-Key: 0196c5d9-2e34-7c24-a47e-a0e1f89bb8a9"Esquecer o cabeçalho em um POST ou PATCH retorna 400 idempotency_key_required. GET, DELETE e outros métodos somente leitura não exigem chave.
3. Retente com a mesma chave em caso de falha
Quando uma requisição estoura o tempo, a conexão cai ou você recebe 5xx, retente com a mesma chave e o mesmo corpo. A BlendFi:
- Se a requisição original deu certo: devolve a mesma resposta (mesmo status, mesmo corpo) sem reexecutar.
- Se a requisição original ainda estiver em andamento (até 60 segundos): retorna
409 idempotency_key_in_progress. Espere e retente. - Se a requisição original falhou com
5xx: reexecutamos a operação. Resultados5xxnunca são cacheados; a falha significa que não sabemos se a operação aconteceu.
async function acceptQuote(quoteId, key) {
for (let attempt = 0; attempt < 4; attempt++) {
const res = await fetch(`${BASE}/v1/quotes/${quoteId}/accept`, {
method: "POST",
headers: {
Authorization: `Bearer ${KEY}`,
"Idempotency-Key": key,
},
});
if (res.status >= 500) {
await sleep(2 ** attempt * 250);
continue;
}
return res.json();
}
throw new Error("accept failed after retries");
}O que se mantém igual entre retentativas
Quando a BlendFi reapresenta uma resposta armazenada, tudo bate com a original:
| Primeira chamada | Chamada repetida (mesma chave) | |
|---|---|---|
| Status HTTP | 201 Created | 201 Created |
| Corpo da resposta | {"id":"01J...","status":"pending",...} | {"id":"01J...","status":"pending",...} (byte por byte) |
| Efeitos colaterais | Transação criada, evento de auditoria emitido | Nenhum, sem segunda transação, sem segundo evento |
| Cabeçalhos | Originais | Originais (exceto content-length, recalculado) |
Sua lógica de retentativa pode tratar uma resposta repetida como se fosse a original. Não precisa detectar "essa é uma repetição"; só fazer parse.
Regras de retentativa em uma tabela
A regra do 4xx vs 5xx
Erros 4xx (validação, conflito, capability ausente) são cacheados. Retentar com a mesma chave devolve o mesmo 4xx; corrija a requisição e use uma chave nova.
Erros 5xx (falhas do lado da BlendFi) não são cacheados. Retentar com a mesma chave reexecuta. Intencional: um 5xx significa que não sabemos se a operação deu certo, então mantemos a chave ativa para retentativas seguras.
| Resultado original | O que acontece na retentativa com a mesma chave |
|---|---|
Sucesso 2xx | Devolve a resposta cacheada. Sem reexecução. |
Erro de cliente 4xx | Devolve o erro cacheado. Use chave nova depois de corrigir. |
Erro do servidor 5xx | Reexecuta. Retentativa é segura. |
| Ainda em andamento (até 60 s) | Retorna 409 idempotency_key_in_progress. Espere. |
| Corpo diferente, mesma chave | Retorna 409 idempotency_key_reused. Bug, investigue. |
Armadilhas comuns
Reaproveitar uma chave em várias operações.
Uma chave está atrelada a uma requisição lógica: um POST /v1/users, um POST /v1/quotes/:id/accept, etc. Reaproveitar uma chave de criação de usuário em uma criação de conversão retorna 409 idempotency_key_reused porque o corpo é diferente.
Gerar uma chave nova por tentativa, em vez de por intenção.
Se o seu loop de retentativa chama randomUUID() dentro do loop, cada retentativa recebe uma chave diferente e a BlendFi trata cada uma como requisição nova. Você cria duplicatas. Gere a chave uma vez, fora do loop.
Descartar chaves antes de retentar em fluxos longos. Registros de idempotência são guardados por 24 horas a partir do primeiro uso. Se a sua retentativa acontecer mais de 24 horas depois, a chave já expirou e a requisição executa do zero. Para fluxos one-shot (criação de usuário, execução de transação) isso não é problema. Para fluxos de vários dias, persista a resposta após a primeira chamada bem-sucedida para não precisar retentar depois da expiração.
Tratar conflito em andamento como erro fatal.
409 idempotency_key_in_progress significa que uma tentativa anterior ainda está rodando. Espere um segundo e retente; não trate como erro fatal.
Quando você não precisa
GET,HEAD,OPTIONS: somente leitura, sem efeito colateral para tratar.DELETE: naturalmente idempotente; deletar um recurso já deletado retorna404, não um delete duplicado.
Para esses métodos, o cabeçalho Idempotency-Key é opcional. Se enviado, é ignorado.
FAQ
Que formato a chave precisa seguir? Qualquer string entre 1 e 255 caracteres. UUID v4 é o recomendado. Não use inteiros sequenciais; colisões entre sistemas viram risco real.
Por quanto tempo a BlendFi guarda uma chave? 24 horas a partir do primeiro uso, por organização. Depois disso, a chave é descartada e uma nova requisição executa do zero se você retentar.
Duas organizações diferentes podem usar a mesma chave?
Podem. Os registros são separados por organização: a idempotency-key: 1234 da Org A é independente da Org B. Sem risco de colisão entre tenants.
E se a minha retentativa atingir uma região diferente da BlendFi? O store de idempotência é centralizado; todas as regiões consultam o mesmo conjunto de registros. Sem execução duplicada por failover regional.
A verificação confere o corpo byte por byte?
Fazemos hash de método + caminho + corpo com SHA-256 e comparamos. Qualquer mudança em qualquer um dos três dispara 409 idempotency_key_reused. Espaços em branco e ordem de chaves no JSON importam: se você serializar diferente na retentativa, bate no check.
E se eu quiser forçar uma reexecução depois de uma requisição bem-sucedida? Use uma chave nova. Não há API para invalidar uma resposta armazenada.
Próximos passos
- Erros e retentativas: a política completa por código de erro, quais são seguros para retentar e com qual backoff.
- Catálogo de erros: cada
codeque a BlendFi pode retornar, status, causa, recuperação.
Verifique e roteie eventos de webhook com segurança
Handler de webhook em nível de produção em Node e Python. Verificação de assinatura, processamento idempotente, padrão de resposta rápida, fila de mensagens com falha (DLQ).
Erros e retentativas
Formato da resposta de erro, política de retentativa por categoria HTTP e como usar request_id no suporte.
