Skip to content

Rate Limits & Versionamento

Limite global

A public-api impõe um teto global de:

200 requisições por minuto, por chave de autenticação

Aplicado via ThrottlerModule.forRoot([{ ttl: 60000, limit: 200 }]) no backend, com janela rolante de 60 segundos. O contador é por accessToken (ou x-api-key legado) — não por IP de origem, e não por endpoint.

Headers de resposta

Toda resposta da public-api inclui os headers de throttle padrão:

http
X-RateLimit-Limit: 200
X-RateLimit-Remaining: 187
X-RateLimit-Reset: 1716475860
HeaderSignificado
X-RateLimit-LimitTeto da janela atual (200).
X-RateLimit-RemainingQuantas requisições ainda cabem antes de bater o teto.
X-RateLimit-ResetUnix timestamp (segundos) em que o contador reseta.

Quando você bate o teto, recebe 429 Too Many Requests:

http
HTTP/1.1 429 Too Many Requests
Retry-After: 23
X-RateLimit-Limit: 200
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1716475883
Content-Type: application/json

{ "statusCode": 429, "message": "Too Many Requests" }

Use Retry-After (em segundos) para agendar a próxima tentativa. Implemente backoff exponencial se receber 429 repetido — geralmente sinaliza que sua App está em loop hot.

Limites por endpoint (planejado)

Hoje não há @Throttle() per-endpoint. A política planejada para o launch público (sem ETA confirmada, gap aberto em public-api-v1.md) é:

EndpointLimite proposto
GET /public/v1/orders60 req/min (paginated reads)
GET /public/v1/menu/items60 req/min
GET /public/v1/reservations60 req/min
POST /public/v1/reservations10 req/min (writes; abuso-prone)

Quando esses limites forem ativados, eles vão aparecer no X-RateLimit-* header e em 429. Construa sua App assumindo os limites futuros desde já — não há benefício em otimizar para o teto global temporário.

Versionamento de API

O path prefixo /public/v1 é o contrato estável de v1. Mudanças incompatíveis (breaking) viram /public/v2. Adições retrocompatíveis (novos campos, novos endpoints) acontecem na v1 sem aviso.

Política de deprecação

Quando um endpoint v1 for deprecado em favor de v2:

  1. Aviso público no changelog em docs/api/changelog.md (em construção) com 90 dias de antecedência.
  2. O endpoint deprecado passa a retornar o header:
http
Sunset: Wed, 23 Aug 2026 00:00:00 GMT
Deprecation: true
Link: </public/v2/orders>; rel="successor-version"
  1. Após a data em Sunset:, o endpoint retorna 410 Gone.

Recomendação: monitore esses headers em sua telemetria. Se sua App vir Deprecation: true, abra task de migração imediatamente.

Boas práticas para evitar bater no teto

  • Cache agressivamente leituras que mudam pouco (menu/items). TTL recomendado: 60 segundos para uso ativo, 5 minutos para uso passivo (relatório noturno).
  • Use webhooks em vez de polling. Se sua App polla GET /orders a cada 30s, troque por subscribe em order.created + order.statusChanged — uma única request a cada evento real.
  • Batch quando possível. Endpoints futuros que aceitarem múltiplos IDs em query (em roadmap) reduzem chamadas drasticamente comparado a fetch-por-ID em loop.
  • Backoff em 429: ao receber 429, espere Retry-After segundos. Em sequência de 429s, dobre o tempo a cada tentativa (jitter ±20% para evitar thundering herd).

CORS e clientes browser

CORS na public-api hoje está restrito a FRONTEND_URL (o frontend do PopinaFlow). Apps server-to-server funcionam normalmente — sem browser, sem CORS.

Apps single-page baseadas em browser não são suportadas em v1. Construa o backend da sua App e proxy as chamadas server-side.

Reportar abuso ou bug de rate limit

Se você suspeita que está sendo throttled incorretamente (ex: tenant alheio consumindo seu teto), abra ticket de suporte com:

  • installationId (visível no painel)
  • Window de timestamps onde ocorreu
  • Sample de X-RateLimit-Remaining observado

Investigação fica no SLA de 2 dias úteis.

Lançado sob a licença MIT.