docs · api
ES
Fundamentos

Rate limits

A API sinaliza excesso de requisições com 429 Too Many Requests e o header Retry-After. As cotas numéricas não são publicadas — não presuma um valor fixo; programe para reagir ao 429 e reduza chamadas com cache.

Como o limite é sinalizado

  • Status 429 com o envelope de erro: error.code: RATE_LIMIT_EXCEEDED, error.retryable: true e error.retryDelay em milissegundos.
  • Header Retry-After (em segundos): quanto esperar antes da próxima tentativa. Respeite-o — repetir antes só prolonga o bloqueio.
429 Too Many Requests
{
  "success": false,
  "error": {
    "message": "Você atingiu o limite de requisições.",
    "code": "RATE_LIMIT_EXCEEDED",
    "type": "rate_limit",
    "statusCode": 429,
    "retryable": true,
    "retryDelay": 60000,
    "requestId": "req_5c26469a-1234-4c8b-9e21-370450bbda3a",
    "docs": "https://docs.draftin.io/errors/RATE_LIMIT_EXCEEDED"
  }
}

Proteções específicas de anúncios

Embora não seja um limite de taxa clássico, o endpoint de clique em anúncios aplica deduplicação por IP: cliques repetidos do mesmo IP no mesmo anúncio dentro de 30 minutos são aceitos com 200, mas não incrementam a métrica. Além disso, cada clickToken é de uso único (reuso retorna 409) e expira em 10 minutos. Veja Anúncios · Delivery.

Boas práticas

  • Cacheie conteúdo publicado. Posts, categorias e tags mudam pouco. Em sites estáticos/SSR, busque no build ou com revalidação por intervalo em vez de a cada visita.
  • Prefira chamadas no servidor. Evite que cada visitante dispare uma requisição direta à API — isso concentra carga e expõe a chave.
  • Respeite o Retry-After ao receber 429, e implemente backoff exponencial para 5xx, com um teto de tentativas.
  • Respeite os limites de paginação (limit até 100 em posts, 50 na busca) e pagine em vez de pedir grandes volumes de uma vez.

Retentativa com backoff

Um wrapper de fetch que repete em erros transitórios e respeita o Retry-After do 429:

TypeScript
async function fetchComRetry(
  url: string,
  init: RequestInit,
  tentativas = 3,
): Promise<Response> {
  let ultimoErro: unknown;

  for (let i = 0; i < tentativas; i++) {
    try {
      const res = await fetch(url, init);

      if (res.status === 429) {
        // respeita o Retry-After do servidor (em segundos)
        const after = Number(res.headers.get("Retry-After") ?? 1);
        await esperar(after * 1000);
        continue;
      }
      if (res.status >= 500) {
        await esperar(2 ** i * 300); // 300ms, 600ms, 1200ms…
        continue;
      }
      return res; // inclui 200, 401, 404…
    } catch (err) {
      ultimoErro = err;
      await esperar(2 ** i * 300);
    }
  }
  throw ultimoErro ?? new Error("Falha após retentativas");
}

const esperar = (ms: number) => new Promise((r) => setTimeout(r, ms));