# Limites de uso Os limites protegem a API para todo mundo e dependem do plano da empresa. Cada **credencial** tem a sua própria cota: uma integração que consome muito não atrapalha as outras credenciais da empresa. ## Limites por plano | Plano | Por minuto | Rajada | Por dia | |---|---|---|---| | Premium | 120 chamadas | até 60 chamadas de uma vez | 100.000 chamadas | | Enterprise | 600 chamadas | até 300 chamadas de uma vez | 1.000.000 de chamadas | Cada chamada conta como uma, seja uma página de 100 itens ou um único recurso. > **Informação**: Melhor esforço > > Os limites são aplicados pelo gateway da API em regime de melhor esforço: números muito próximos do teto podem passar ou ser barrados com pequena diferença. Planeje com folga em vez de rodar colado no limite. Existe ainda uma proteção por endereço IP: acima de 6.000 requisições em 5 minutos a partir do mesmo IP, o gateway bloqueia as chamadas, independentemente do plano. Essa resposta de bloqueio vem do firewall e não é uma das respostas de erro documentadas em [Erros](https://developers.festero.com.br/errors.md). ## Cabeçalhos de limite Toda resposta autenticada traz os limites do seu plano: | Cabeçalho | Exemplo | Significado | |---|---|---| | `X-RateLimit-Limit` | `120` | Chamadas permitidas por minuto. | | `X-RateLimit-Policy` | `120;w=60, 100000;w=86400` | Limite por minuto (janela de 60 s) e por dia (janela de 86400 s). | Os valores são fixos do plano. Não existe cabeçalho com "chamadas restantes" nem com a hora do reinício: se precisar saber quanto já gastou, conte no seu lado. ## Quando o limite estoura: 429 Passou do limite por minuto ou da cota diária? A API responde `429` com o código [`rate_limited`](https://developers.festero.com.br/errors.md#rate_limited) e o cabeçalho `Retry-After: 60`: ```http HTTP/1.1 429 Too Many Requests Content-Type: application/problem+json Retry-After: 60 ``` ```json { "type": "https://developers.festero.com.br/errors#rate_limited", "title": "Too Many Requests", "status": 429, "detail": "Rate limit per minute exceeded. Retry after the interval in Retry-After.", "code": "rate_limited", "requestId": "6f1c2a9e-0b7d-4c1e-9a52-3e8f7d1c0a44" } ``` O texto de `detail` informa qual limite estourou: `Rate limit per minute exceeded...` para o limite por minuto, ou `Daily quota exceeded...` para a cota do dia. - **Limite por minuto:** espere o tempo do `Retry-After` (60 segundos) e continue num ritmo menor. - **Cota diária:** o `Retry-After` de 60 segundos é um valor fixo do gateway. Como a cota é diária, esperar um minuto não resolve; reduza o volume diário de chamadas. ## Boas práticas 1. **Use `sales-summary` em vez de paginar tudo.** Para saber quanto foi vendido e recebido num período, uma chamada a [`GET /v1/finance/sales-summary`](https://developers.festero.com.br/api/financeiro.md#resumo-de-vendas) substitui centenas de páginas de eventos e recebíveis. 2. **Sincronize só o que mudou.** Guarde o instante da última sincronização e use `updatedSince`. Veja [Paginação e datas](https://developers.festero.com.br/paginacao.md#sincronizacao-incremental). 3. **Peça páginas grandes.** Com `limit=100` você faz um quarto das chamadas que faria com o padrão de 25. 4. **Prefira webhooks a consultas repetidas.** Em vez de perguntar a cada minuto se algo mudou, deixe o Festero avisar: [Webhooks](https://developers.festero.com.br/webhooks.md). 5. **Reaproveite o token.** Ele vale 60 minutos. Veja [Autenticação](https://developers.festero.com.br/autenticacao.md#guardar-o-token). 6. **Use `ETag`.** Ao reler um recurso individual, envie o `ETag` recebido em `If-None-Match`; se nada mudou, a resposta é `304`, sem corpo. 7. **Respeite o `Retry-After` e use espera crescente.** Em `429`, `500`, `502` e `504`, tente de novo esperando mais a cada tentativa. 8. **Evite rajadas paralelas.** Enviar centenas de chamadas ao mesmo tempo esgota a rajada mesmo com a média baixa. ## Exemplo: repetir com espera crescente ```js async function chamar(url, token, tentativas = 5) { for (let tentativa = 1; ; tentativa++) { const resposta = await fetch(url, { headers: { Authorization: `Bearer ${token}` } }) const repetivel = [429, 500, 502, 504].includes(resposta.status) if (!repetivel || tentativa === tentativas) return resposta // Em 429, o gateway diz quanto esperar. Nos demais casos, espera crescente: 1 s, 2 s, 4 s... const retryAfter = Number(resposta.headers.get('Retry-After')) const esperaMs = retryAfter > 0 ? retryAfter * 1000 : 2 ** (tentativa - 1) * 1000 await new Promise((resolver) => setTimeout(resolver, esperaMs)) } } ```