Pular para o conteúdo

API v1 · Guia

Idempotência

Repita POST, PATCH e DELETE com segurança usando o cabeçalho Idempotency-Key.

A conexão cai depois que o pedido chegou e antes de a resposta voltar. Sem idempotência, repetir pode criar o registro duas vezes. Com o cabeçalho Idempotency-Key, a segunda tentativa devolve a resposta da primeira e nada roda de novo.

Para repetir com segurança um POST, PATCH ou DELETE (depois de uma queda de conexão, por exemplo), envie o cabeçalho Idempotency-Key com um valor único por operação, como um UUID. O cabeçalho é opcional.

  • Mesma chave e mesmo pedido (método, caminho e corpo idênticos, byte a byte) dentro de 24 horas: a operação não roda de novo. Você recebe a resposta guardada da primeira vez, com o cabeçalho Idempotent-Replayed: true.
  • Mesma chave com outro pedido: 409 idempotency_key_reused. Gere uma chave nova.
  • Mesma chave enquanto o primeiro pedido ainda está em andamento: 409 idempotency_key_in_progress. Espere a resposta do primeiro e repita.
  • Respostas 429 e de erro 5xx não ficam guardadas: repetir com a mesma chave executa de novo. Os demais erros 4xx ficam guardados como qualquer resposta.

A chave vale só para o token que a enviou. Em pedidos GET ela é ignorada.

Exemplo

Terminal
curl -X POST "https://rumocrm.com/api/v1/contacts" \
  -H "Authorization: Bearer $RUMO_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2d7e-8a4b-4c3d-9e2f-0a1b2c3d4e5f" \
  -d '{"name": "Maria Souza", "phone": "(15) 99807-3400"}'

Repetir com a mesma chave

Gere a chave uma vez por operação e guarde junto dela (na fila, por exemplo). Uma chave nova a cada tentativa desliga a proteção.

Node.js
import { randomUUID } from "node:crypto";

// A chave nasce junto com a operação, antes da primeira tentativa, e vai em todas.
async function criarContato(dados, tentativas = 4) {
  const chave = randomUUID();
  for (let tentativa = 1; ; tentativa++) {
    try {
      const resposta = await fetch("https://rumocrm.com/api/v1/contacts", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.RUMO_TOKEN}`,
          "Content-Type": "application/json",
          "Idempotency-Key": chave,
        },
        body: JSON.stringify(dados),
      });
      if (resposta.status < 500 || tentativa === tentativas) return resposta;
    } catch (erroDeRede) {
      if (tentativa === tentativas) throw erroDeRede;
    }
    await new Promise((pronto) => setTimeout(pronto, 2 ** tentativa * 500));
  }
}
PróximoLimites de requisição