Limites de uso (rate limiting)
A API do InHire aplica um limite de requisições por conta para garantir estabilidade e tempo de resposta consistente para todos os clientes. Esta página descreve como esse limite é calculado, como acompanhar seu consumo em tempo real e como sua integração deve se comportar quando o limite é atingido.
Como o limite é calculado
O limite é por conta, não por token de acesso.
Todas as requisições autenticadas com usuários de API da sua conta compartilham o mesmo saldo. Se você tem mais de um usuário de API (por exemplo, um para sincronizar seu ERP e outro para alimentar seu site de carreiras), os dois consomem do mesmo limite.
Requisições feitas por pessoas usando a plataforma web não contam para esse limite. Ele se aplica somente ao acesso programático via API.
O controle usa o algoritmo de balde de fichas (token bucket):
- Sua conta tem um balde com uma capacidade máxima de fichas, chamada de burst.
- Cada requisição consome uma ficha.
- O balde é reabastecido continuamente, na taxa sustentada da sua conta.
- Uma requisição que chega com o balde vazio recebe
429 Too Many Requests.
Limites
| Valor | |
|---|---|
| Taxa sustentada | 20 requisições/segundo |
| Burst | 400 requisições |
A taxa sustentada é o volume que você pode manter indefinidamente. O burst é quanto você pode disparar acima dessa taxa em um pico, aproveitando as fichas acumuladas enquanto sua integração estava ociosa.
Entendendo o burst
O burst existe para que picos legítimos não sejam penalizados. Uma integração que ficou parada acumula fichas e pode disparar um lote rapidamente, sem tomar 429.
Veja o comportamento do limite ao longo do tempo:
| Momento | O que a integração faz | Fichas no balde | Resultado |
|---|---|---|---|
t = 0s | está ociosa | 400 (cheio) | balde no máximo |
t = 0s a t = 3s | dispara 400 requisições (~133/s) | 400 → 60 | todas passam |
t = 3s a t = 3,5s | mantém as ~133/s | 60 → 0 | balde esvazia |
a partir de t = 3,5s | mantém as ~133/s | 0 | recebe 429 |
a partir de t = 3,5s | reduz para 20/s | 0, estável | todas passam |
| pausa de 20 segundos | não faz requisições | 0 → 400 | burst recarregado |
Na prática, isso significa:
- Sincronização em lote. Paginar 5.000 candidaturas: as primeiras 400 requisições passam na velocidade que sua rede permitir, e as 4.600 restantes saem a 20/s. O trabalho todo leva cerca de 4 minutos, sem nenhum
429, desde que sua integração mantenha o ritmo em vez de despejar tudo de uma vez. - Pico disparado por evento. 100 candidaturas chegam de uma vez e sua integração busca os dados de cada uma: são 100 requisições contra um burst de 400, absorvidas integralmente, sem
429. - Laço com defeito. Uma integração em loop a 200 req/s consome as 400 fichas em cerca de 2 segundos e passa a receber
429na maior parte das requisições seguintes, até reduzir o ritmo.
Acompanhando seu consumo
Toda resposta da API inclui três headers que permitem acompanhar o saldo sem precisar provocar um 429:
| Header | Significado |
|---|---|
X-RateLimit-Limit | Capacidade total do balde da sua conta |
X-RateLimit-Remaining | Fichas disponíveis no momento da resposta |
X-RateLimit-Reset | Timestamp Unix (em segundos) de quando o balde volta a ficar cheio |
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 400
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1785874957
X-RateLimit-Limit é a capacidade do balde, não o número de requisições permitidas por segundo. Esse header retorna 400, mas sua taxa sustentada é de 20 requisições por segundo. Não use o valor do header para dimensionar a velocidade da sua integração.
Recomendamos monitorar X-RateLimit-Remaining e desacelerar preventivamente quando ele ficar baixo, em vez de acelerar até tomar 429.
Quando o limite é excedido
Requisições acima do limite recebem o status 429 Too Many Requests:
{
"message": "Rate limit exceeded"
}
A resposta traz o header Retry-After, além dos headers de consumo:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 1
X-RateLimit-Limit: 400
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1785874977
Use Retry-After para agendar a próxima tentativa. Ele vem em segundos, arredondado para cima, com valor mínimo de 1.
Não use X-RateLimit-Reset para decidir quando repetir a requisição. Ele marca quando o balde volta a ficar cheio, o que a partir de um balde vazio está a 20 segundos de distância, enquanto uma única ficha é reposta em 50 milissegundos. Esperar o Reset para retentar desperdiça quase toda a capacidade disponível nesse intervalo. Esse header serve para você entender quando recupera o burst inteiro, não quando a próxima requisição passa.
O limite é aplicado antes da requisição chegar à API, então um 429 garante que a operação não foi executada. Repetir a requisição é seguro, inclusive em POST e PUT, sem risco de duplicar recursos. Essa garantia vale só para o 429: em erros 5xx ou timeout, a operação pode ter sido processada, e a repetição precisa de cuidado.
Boas práticas
Use backoff exponencial com jitter
Ao receber 429, espere e tente novamente com intervalos crescentes. Some um valor aleatório (jitter) a cada espera para evitar que várias tentativas colidam no mesmo instante.
async function requestWithRetry(url, options, maxAttempts = 5) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const response = await fetch(url, options);
if (response.status !== 429) return response;
// Header ausente ou inválido cai para 1 segundo.
const headerSeconds = Number(response.headers.get("retry-after"));
const retryAfter = headerSeconds >= 1 ? headerSeconds : 1;
const backoffSeconds = retryAfter * 2 ** attempt;
const jitterSeconds = Math.random() * backoffSeconds * 0.3;
await new Promise((resolve) =>
setTimeout(resolve, (backoffSeconds + jitterSeconds) * 1000),
);
}
throw new Error("Limite de requisições persistente após várias tentativas");
}
Prefira webhooks a polling
Consultar a API em intervalos curtos para descobrir o que mudou é o padrão que mais consome limite, e quase sempre pode ser substituído. Com webhooks, o InHire notifica seu sistema quando algo acontece, e você faz requisições apenas sobre os registros que realmente mudaram.
Limite a concorrência
Disparar muitas requisições em paralelo esvazia o burst em poucos segundos e o ganho é menor do que parece, porque a taxa sustentada é a mesma. Mantenha um número fixo de requisições simultâneas (algo entre 5 e 20 atende à maioria dos casos) em vez de disparar tudo de uma vez.
Pagine com o maior tamanho de página disponível
Trazer mais registros por requisição reduz o número total de chamadas para percorrer o mesmo volume de dados. Consulte o guia do endpoint para saber o tamanho máximo de página suportado.
Cacheie dados estáveis
Vagas, campos personalizados e definições de scorecard mudam com pouca frequência. Guardar esses dados do seu lado e revalidar periodicamente evita repetir as mesmas consultas.
Mudanças nesta política
Os limites descritos aqui podem ser ajustados. Qualquer alteração que reduza a capacidade disponível será comunicada com pelo menos 30 dias de antecedência e precedida de um período em que o novo limite é medido, mas não aplicado, para que você possa se adaptar sem impacto.