Limites de débit (Rate limits)
Limites appliquées sur l'API Diamond Careers, comment les détecter dans les réponses et dimensionner votre intégration.
L'API Diamond Careers applique un rate limiting par fenêtre fixe sur chaque requête entrante. Cela protège la plateforme contre les bruteforces de login, les scrapings non autorisés et les pics de requêtes générés par un compte compromis.
Toutes les réponses sous /diamond/v1/* (et les endpoints d'authentification associés) renvoient les en-têtes RFC draft IETF :
X-RateLimit-Limit— limite de la fenêtre courante.X-RateLimit-Remaining— requêtes restantes avant 429.X-RateLimit-Reset— secondes avant réinitialisation de la fenêtre.
Au dépassement, l'API renvoie 429 Too Many Requests avec un en-tête Retry-After (secondes).
Tiers appliqués
Plusieurs tiers cohabitent. Le plus restrictif gagne : si vous saturez une fenêtre minute, vous prenez 429 même si la fenêtre heure n'est pas encore atteinte.
Authentification (par IP)
Endpoints concernés : POST /wp-json/jwt-auth/v1/token, POST /diamond/v1/auth/login, GET /diamond/v1/auth/bootstrap.
| Fenêtre | Limite |
|---|---|
| 60 s | 10 requêtes |
| 1 h | 60 requêtes |
Tier strict pour bloquer les bruteforces de mot de passe. Il s'applique à l'IP source, indépendamment de l'utilisateur ciblé.
Mutations (par utilisateur)
POST, PATCH, PUT, DELETE sur /diamond/v1/* après authentification.
| Fenêtre | Limite |
|---|---|
| 60 s | 60 requêtes |
| 1 h | 600 requêtes |
Tier dimensionné pour des intégrations type ATS qui poussent des offres et mettent à jour des candidatures à un rythme humain ou automatisé raisonnable.
Lectures (par utilisateur)
GET/HEAD sur /diamond/v1/* après authentification.
| Fenêtre | Limite |
|---|---|
| 60 s | 300 requêtes |
| 1 h | 3 000 requêtes |
Volume plus large : lecture est moins coûteuse, et un client typique en consomme nettement plus que de mutations.
Anonymes (par IP)
/diamond/v1/* sans token ni session valide (lectures publiques, signup, contact).
| Fenêtre | Limite |
|---|---|
| 60 s | 60 requêtes |
| 1 h | 600 requêtes |
Endpoints exclus
POST /diamond/v1/offres/{id}/track-view— déjà rate-limité indépendamment (1 vue par IP par offre toutes les 24 heures).
Détecter une limite atteinte
Au dépassement :
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 42
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 42{
"code": "too_many_requests",
"message": "Limite de débit dépassée. Réessayez dans 42 secondes.",
"data": {
"status": 429,
"retry_after": 42,
"tier": "auth_min"
}
}Le champ data.tier indique laquelle des fenêtres a été saturée (auth_min, auth_hour, mut_min, mut_hour, read_min, read_hour, anon_min, anon_hour).
Surveiller votre consommation
Les en-têtes X-RateLimit-* sont retournés sur toutes les réponses (pas uniquement 429), ce qui permet une surveillance en temps réel :
HTTP/1.1 200 OK
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 42Si Remaining descend trop vite, ralentissez avant de prendre un 429.
Stratégies pour respecter les limites
Backoff exponentiel sur 429
async function callWithBackoff(url, options, maxRetries = 5) {
let attempt = 0;
while (attempt < maxRetries) {
const response = await fetch(url, options);
if (response.status !== 429) return response;
const retryAfter = parseInt(response.headers.get('Retry-After') || '1', 10);
const backoff = Math.max(retryAfter, Math.pow(2, attempt));
await new Promise(r => setTimeout(r, backoff * 1000));
attempt++;
}
throw new Error('Limite de débit persistante.');
}Étaler dans le temps
const ITEMS_PER_SECOND = 5;
for (const item of items) {
await processItem(item);
await new Promise(r => setTimeout(r, 1000 / ITEMS_PER_SECOND));
}Paralléliser raisonnablement
import pLimit from 'p-limit';
const limit = pLimit(5); // max 5 requêtes en parallèle
const results = await Promise.all(
items.map(item => limit(() => processItem(item)))
);Réduire le nombre d'appels
- Cachez les ressources peu changeantes (taxonomies, listes de villes, catégories).
- Filtres précis plutôt que récupération massive puis filtrage côté client.
- Synchronisation par delta (
filter[modified_after]) plutôt que tout re-télécharger. - Augmentez
per_page=100pour réduire le nombre d'appels par parcours.
Configuration et tuning
Les seuils par défaut sont dimensionnés pour les cas d'usage typiques. Si votre intégration justifie un volume contractuellement supérieur, contactez tech@diamondcareers.fr avec votre cas d'usage et le pic horaire attendu — nous pouvons relever les tiers pour votre compte technique.
Tous les tiers sont configurables via le filtre WordPress diamond/rate_limiter/tiers côté plateforme (à toucher avec précaution).
Mesures anti-abus
Le rate limit standard est complété par une surveillance manuelle des comportements. Nous nous réservons le droit de suspendre un compte technique dont l'usage présente :
- volume manifestement disproportionné par rapport au cas d'usage déclaré,
- pattern de requêtes typique d'un scraping non autorisé (parcours exhaustif des CVthèques),
- activité concentrée sur des données sensibles à un rythme anormal après authentification.
Toute suspension est suivie d'un email au contact technique du compte. Si vous l'estimez injustifiée, répondez pour clarifier — chaque cas est étudié individuellement.
Stockage et fiabilité
Les compteurs sont stockés dans le cache d'objet WordPress (Redis sur l'infra actuelle, donc atomicité préservée et persistance entre requêtes). En cas de défaillance du backend cache, un fallback transient est utilisé : la fenêtre garde son comportement, avec une légère tolérance aux courses de concurrence.