Skip to main content
A obrigatoriedade do header Idempotency-Key varia por motor:
  • Motor de CPF/CNPJ (POST /analyses): o header é obrigatório. Sem ele (ou com valor vazio), a API responde 400 bad_request com a mensagem “Idempotency-Key header required”.
  • Motor de Borderô (POST /operations): o header é opcional. Presente, funciona como nos analyses (replay devolve 200 com o body original; key reusada com payload diferente devolve 409 idempotency_conflict). Ausente, cada POST cria uma operação nova — e uma cobrança nova.
O motivo para usar a key mesmo onde é opcional é simples: rede falha. Um timeout no seu lado não significa que a requisição não chegou — a análise ou operação pode ter sido criada e os tokens debitados sem que você tenha recebido a resposta. Sem idempotência, repetir a chamada criaria uma segunda cobrança. Com a Idempotency-Key, repetir é sempre seguro: a API reconhece a repetição e devolve a resposta original, sem cobrar de novo.

Como funciona (os dois motores)

A deduplicação vale por uma janela de 24 horas a partir da primeira requisição. Repare no status code: 202 significa “criei agora”; 200 significa “isto é um replay — nada novo foi criado nem cobrado”. Seu código pode tratar os dois como sucesso, já que o body é o mesmo.

O que conta como “mesmo conteúdo”

A comparação cobre o payload inteiro do POST, em cada motor: No borderô, reenviar exatamente o mesmo multipart com a mesma key é um replay (200). Trocar o arquivo, o ZIP de NFe ou qualquer campo mantendo a mesma key resulta em 409 idempotency_conflict.

Concorrência

Se duas requisições com a mesma key chegarem ao mesmo tempo, a primeira vence. A concorrente recebe 409 enquanto a primeira ainda está em andamento. Não gere uma key nova nesse caso: aguarde um instante e consulte o resultado via GET (/analyses/{id} ou /operations/{id}), usando o id da resposta 202 original. Se você ainda não tem o id (por exemplo, a primeira chamada deu timeout no seu lado), repita o POST com a mesma key até receber 200 (replay) ou 202 (se a primeira chamada nunca chegou ao servidor).

Receita prática

  1. Derive a key do ID interno do seu job. Gere um UUID no momento em que o job (ou o borderô) é criado no seu sistema e persista junto com ele. UUID é o formato recomendado. Uma key por requisição pretendida — nunca reutilize a mesma key para documentos, arquivos ou jobs diferentes.
  2. Timeout ou 5xx → repita com a MESMA key. A resposta será a 202 original (se a primeira chamada não chegou) ou um replay 200 (se chegou). Nos dois casos, sem cobrança dupla.
  3. 4xx de validação → corrija e use uma key NOVA. A key antiga está amarrada ao conteúdo antigo: mesma key + conteúdo corrigido resulta em 409 idempotency_conflict.
Nunca gere uma key nova ao repetir uma requisição que falhou por timeout ou 5xx. Uma key nova cria uma cobrança nova — no borderô, uma por entidade única do arquivo.
Os Motores usam a mesma base da API 221b (https://221b-api.sherlocker.com.br/api/v1), mas autenticam via Authorization: Bearer slhk_…não via ?token=.

Retry na prática

Os três cenários:
  1. Primeira submissão → 202. Análise criada, tokens debitados.
  2. Replay (mesma key, mesmo body) → 200. O mesmo body JSON da 202, byte a byte — mesmo id, mesmos tokens_charged e balance, mesmo request_id. Nada foi criado nem cobrado de novo.
  3. Mesma key, body diferente → 409. Por exemplo, a mesma key com um purpose adicionado:
cURL
Resposta (409, application/problem+json) — igual nos dois motores:
O mesmo code (idempotency_conflict) é retornado tanto no conflito de conteúdo quanto na concorrência. Faça branching pelo code, não pelo texto de detail, que pode variar. Detalhes em Erros e idempotency_conflict.

Próximos passos

Ciclo de vida

Status e como fazer polling em cada motor

Cobrança

Quando os tokens são debitados e quando há estorno

Erros

Formato RFC 7807 e todos os códigos de erro