Idempotency-Key.
Envie um, e a repetição recebe a mesma resposta de volta — mesmo status,
mesmo corpo — em vez de executar outra vez.
201
201 com created: true:
200 com created: false — correto,
e inútil para o código que a fez. Um programa que provisiona um workspace quando
created é verdadeiro não consegue distinguir “outra pessoa já fez isso” de “a
minha própria repetição passou”.
Escolhendo uma chave
Qualquer valor opaco, até 255 caracteres. Um UUID por tentativa é a resposta usual; o seu próprio identificador da operação (order_8421-refund) também
funciona, e tem a vantagem de que um processo que recomeça do zero gera o mesmo.
A chave é escopada pela sua chave de API e pela rota. Dois inquilinos
enviando Idempotency-Key: 1 nunca colidem, uma chave live nunca repete o que
uma chave test respondeu, e a mesma chave em outro endpoint é outra operação.
As chaves são lembradas por 24 horas. Toda repetição que algum dia vai
carregar uma delas acontece dentro dessa janela — o backoff de um cliente é de
segundos, a reentrega de uma fila é de minutos, uma pessoa reexecutando um job
que falhou é de horas. Um dia depois você não está repetindo, está chamando de
novo, e deve enviar uma chave nova.
As três respostas que uma repetição pode receber
Repetida — a mesma resposta
Repetida — a mesma resposta
A primeira requisição terminou. Você recebe o status e o corpo dela, mais
Idempotent-Replay: true. O handler não roda.409 — ainda em execução
409 — ainda em execução
Outra requisição com essa chave está em voo. Exatamente uma delas chega ao
handler, por construção — então isso não é uma corrida que você perdeu, é a
corrida sendo fechada. Espere o
Retry-After e tente de novo; você vai
receber a resposta repetida.409
422 — a chave foi usada para outra coisa
422 — a chave foi usada para outra coisa
A chave já está registrada com outro corpo ou outra query string. Repetir a
primeira resposta aqui diria que uma chamada deu certo quando ela nunca
aconteceu, então ela é recusada.Isso quase sempre significa uma chave reaproveitada sem querer — uma
constante esquecida no código, ou uma repetição que remontou o payload a
partir de um estado que mudou. Gere uma chave por operação, não por processo.
422
Falha não é resultado
Uma requisição que respondeu5xx, ou que foi barrada pelo limite de taxa antes
de chegar ao handler, não deixou nada para trás. A chave dela volta para a
prateleira: repita com a mesma chave e a requisição executa.
Uma requisição que respondeu 201 criou algo, e a chave dela está gasta. A que
respondeu 400 também — o mesmo corpo vai produzir o mesmo 400, e repeti-lo
não custa nada a você.
Essa assimetria é a regra inteira, e é o que torna correto o laço de repetição
ingênuo:
1
Gere uma chave para a operação
Antes da primeira tentativa, não dentro dela.
2
Envie em todas as tentativas
Mesma chave, mesmo corpo.
3
Trate 409 como 'ainda não'
Faça backoff e tente de novo. Trate
422 como um bug do seu próprio código —
uma chave nova não conserta uma chave reaproveitada, esconde.Onde vale
Só na superfície da chave secreta,uk_sk_…. Leituras ignoram o header: repetir
um GET devolveria uma resposta velha para uma pergunta que você fez justamente
porque queria uma nova.
As superfícies chamadas do navegador — /v1/boot, /v1/contact-auth/*,
/v1/contact/* — não aceitam o header. Elas são dirigidas por uma pessoa, e os
fluxos que poderiam duplicar já são de uso único por construção: um magic link,
um código por e-mail e um callback social são gastos pela primeira requisição que
os resgata.
POST /v1/contacts resolve para a mesma pessoa, seja chamado uma ou dez vezes —
valores identificadores nunca reapontam para um segundo contato. A chave é o que
torna a resposta estável também, e é nela que o seu código de fato ramifica.