> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shappire.tools/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate limiting

> Limites de requisição na API pública Shappire

A API pública aplica limites por API key, por projeto e por IP para proteger a infraestrutura.

## Limites por API key / projeto

| Limite             | Valor padrão | Escopo                                | Variável de ambiente        |
| ------------------ | ------------ | ------------------------------------- | --------------------------- |
| Requisições/minuto | 60           | Por API key                           | `API_RATE_LIMIT_PER_MINUTE` |
| Requisições/dia    | 1.000        | Por projeto (todas as chaves)         | `API_DAILY_LIMIT`           |
| Jobs simultâneos   | 2            | Por projeto (`queued` + `processing`) | `API_MAX_CONCURRENT_JOBS`   |

<Warning>
  Jobs em status `queued` ou `processing` contam para o limite de concorrência. Aguarde `completed` ou `failed` antes de enfileirar novos downloads.
</Warning>

## Headers de resposta (rotas autenticadas)

Em requisições autenticadas bem-sucedidas, a API retorna:

| Header                  | Significado                                         |
| ----------------------- | --------------------------------------------------- |
| `X-RateLimit-Limit`     | Máximo na janela atual (por minuto)                 |
| `X-RateLimit-Remaining` | Requisições restantes na janela                     |
| `X-RateLimit-Reset`     | Unix timestamp absoluto do início do próximo minuto |

`X-RateLimit-Reset` é um epoch timestamp — não segundos restantes.

Em respostas `429` por rate limit da API key, esses headers **não** são enviados.

## Códigos de erro `429`

| Código                       | Situação                               |
| ---------------------------- | -------------------------------------- |
| `rate_limit_exceeded`        | Mais de 60 req/min na mesma chave      |
| `daily_limit_exceeded`       | Cota diária do projeto esgotada        |
| `concurrency_limit_exceeded` | Mais de 2 jobs de download simultâneos |

Corpo típico:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests per minute.",
    "request_id": "req_abc123"
  }
}
```

## Limites globais por IP

Antes do router `/v1`, a infraestrutura aplica limites adicionais por IP:

| Limiter | Janela | Limite     |
| ------- | ------ | ---------- |
| Global  | 60 s   | 100 req/IP |
| Burst   | 5 s    | 30 req/IP  |

Formato de erro diferente (sem `request_id`):

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "error": {
    "code": "error.api.rate_limited",
    "message": "Muitas requisições. Aguarde."
  }
}
```

Headers seguem o padrão draft-6 (`Ratelimit-Limit`, `Ratelimit-Remaining`, etc.).

Em integrações server-to-server normais, o limite por API key é o que importa. Os limites por IP afetam principalmente tráfego sem autenticação ou abusivo.

## Boas práticas

* Implemente backoff exponencial em `429` e `5xx`
* Use `GET /jobs/{jobId}` com intervalo de 2–5 s — não faça polling agressivo em `/media/resolve`
* Registre `request_id` nos logs para suporte
* Use fila no seu backend para respeitar o limite de 2 jobs simultâneos

Veja também: [Polling e retentativas](/pages/guides/polling-e-retentativas) · [Boas práticas](/pages/guides/boas-praticas)
