BlendFi

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.

Confiabilidade

Idempotência

Uma chave de idempotência é como um post-it grudado na sua requisição. Se sua rede cai no meio de um POST /v1/transactions e você não sabe se a transação foi criada, você tenta de novo com a mesma chave — e 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 um cabeçalho Idempotency-Key. Este guia mostra como usar do jeito certo.

Resumo

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). Reuse 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ê reusa uma chave para uma requisição diferente sem querer, recebe `409 idempotency_key_reused`. Isso protege você dos 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 coisa 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 você tentar de novo, reuse a mesma chave.

2. Envie a chave em todo POST e PATCH

Adicione no cabeçalho Idempotency-Key em toda requisição que escreve dado:

curl -X POST $BLENDFI_BASE/v1/transactions \
  -H "Authorization: Bearer $BLENDFI_KEY" \
  -H "Idempotency-Key: 0196c5d9-2e34-7c24-a47e-a0e1f89bb8a9" \
  -H "content-type: application/json" \
  -d '{"quote_id": "01J..."}'

Se você esquecer o cabeçalho num POST ou PATCH, a BlendFi rejeita com 400 idempotency_key_required. GET, DELETE e outros métodos somente leitura não precisam.

3. Tente de novo com a mesma chave em caso de falha

Quando uma requisição estoura o tempo, a conexão cai ou você recebe um 5xx — tente de novo com a mesma chave e o mesmo corpo. A BlendFi vai:

  • 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 (menos de 60 segundos), retorna 409 idempotency_key_in_progress. Espere e tente de novo.
  • Se a requisição original falhou com 5xx, reexecuta a operação. Resultados 5xx nunca são cacheados, porque a falha significa que a gente não sabe se a operação aconteceu de fato.
async function createTransaction(quoteId, key) {
  for (let attempt = 0; attempt < 4; attempt++) {
    const res = await fetch(`${BASE}/v1/transactions`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${KEY}`,
        "Idempotency-Key": key,
        "content-type": "application/json",
      },
      body: JSON.stringify({ quote_id: quoteId }),
    });

    if (res.status >= 500) {
      await sleep(2 ** attempt * 250);
      continue;
    }
    return res.json();
  }
  throw new Error("transaction failed after retries");
}

O que se mantém igual entre retentativas

Quando a BlendFi reexibe uma resposta armazenada, tudo bate com a original:

Primeira chamadaChamada repetida (mesma chave)
Status HTTP201 Created201 Created
Corpo da resposta{"id":"01J...","status":"pending",...}{"id":"01J...","status":"pending",...} (byte por byte)
Efeitos colateraisTransação criada, evento de auditoria emitidoNenhum — sem segunda transação, sem segundo evento de auditoria
CabeçalhosOriginaisOriginais (exceto content-length, recalculado)

Isso significa que sua lógica de retentativa pode tratar uma resposta repetida como se fosse a original. Você não precisa detectar "essa é uma repetição" — só fazer parse.

Regras de retentativa em uma lista

A regra do 4xx vs 5xx

Erros na faixa 4xx (falhas de validação, conflitos, capacidades faltando) são cacheados. Tentar de novo com a mesma chave devolve o mesmo 4xx — corrija a requisição e use uma chave nova.

Erros na faixa 5xx (falhas do lado da BlendFi) não são cacheados. Tentar de novo com a mesma chave reexecuta a operação. Isso é intencional: um 5xx quer dizer que a gente não sabe se a operação deu certo, então mantemos a chave ativa para retentativas.

Resultado originalO que acontece na retentativa com a mesma chave
Sucesso 2xxDevolve a resposta cacheada. Sem reexecução.
Erro de cliente 4xxDevolve o erro cacheado. Use chave nova após corrigir.
Erro do servidor 5xxReexecuta. Retentativa é segura.
Ainda em andamento (até 60 s)Retorna 409 idempotency_key_in_progress. Espere.
Corpo diferente, mesma chaveRetorna 409 idempotency_key_reused. Bug — investigue.

Armadilhas comuns

Reusar uma chave em várias operações. Uma chave está atrelada a uma requisição lógica — um POST /v1/users, um POST /v1/transactions, etc. Se você reusa uma chave de criação de usuário numa criação de transação, recebe 409 idempotency_key_reused porque o corpo é diferente.

Gerar uma chave nova por tentativa em vez de por intenção. Se seu loop de retentativa chama randomUUID() dentro do loop, cada retentativa recebe uma chave diferente, e a BlendFi trata cada uma como uma requisição nova. Você vai criar duplicatas. Gere a chave uma vez, fora do loop.

Descartar chaves antes de tentar de novo em fluxos longos. O sandbox guarda registros de idempotência por 24 horas. Se 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 tentar de novo 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 tente de novo — não dê erro fatal.

Quando você não precisa

Requisições somente leitura (GET, HEAD, OPTIONS) não precisam de chave de idempotência. Não têm efeito colateral para deduplicar. O cabeçalho só é rejeitado nesses métodos se você passar com valores conflitantes explicitamente.

DELETE é naturalmente idempotente — deletar um recurso já deletado retorna 404, não um delete duplicado. Por isso a gente não exige chave de idempotência em DELETE.

O que ler em seguida

FAQ

Que formato a chave precisa ter? Qualquer string entre 1 e 255 caracteres. UUID v4 é o recomendado. Não use inteiros sequenciais — colisões entre sistemas viram um risco real.

Por quanto tempo a BlendFi lembra de uma chave? 24 horas a partir do primeiro uso, por organização. Depois disso, a chave é esquecida e uma requisição nova executa do zero se você tentar de novo.

Duas organizações diferentes podem usar a mesma chave? Podem. Os registros de idempotência são separados por organização, então a idempotency-key: 1234 do parceiro A é independente da do parceiro B. Não tem risco de colisão entre tenants.

E se minha retentativa atingir uma região diferente da BlendFi? O store de idempotência da BlendFi é centralizado — todas as regiões consultam o mesmo conjunto de registros. Você não vai ter execução duplicada por failover regional.

A verificação de idempotência confere o corpo da requisição byte por byte? A gente faz hash de método + caminho + corpo com SHA-256 e compara. Qualquer mudança em qualquer um dos três dispara 409 idempotency_key_reused. Espaços em branco e ordem das chaves no JSON importam — se você serializar diferente na retentativa, vai bater no check.

E se eu quiser forçar uma reexecução depois de uma requisição que deu certo? Use uma chave nova. Não tem API para invalidar uma resposta armazenada.

Nesta página