Limites de requêtes
Quotas, en-têtes X-RateLimit et la bonne stratégie d'attente progressive.
Wajub limite le débit sur plusieurs axes à la fois : votre compte, la clé utilisée et quelques
endpoints sensibles, ou l'IP appelante quand la requête ne porte aucune clé. Une requête doit
passer toutes ces limites. La première qui se déclenche décide de votre 429.
Les limites de la plateforme sont ailleurs
Cette page traite de la limitation des requêtes. Pour la taille des fichiers envoyés, le plafond des payloads de webhook et les quotas de compte, consultez Plafonds et quotas.
Les limites
| Portée | Plafond par tranche de 60 secondes | Compté par |
|---|---|---|
| Non authentifié | 30 | IP appelante, seulement pour un appel sans clé |
| Compte | Votre plan : 120 sur Pay as you go, 360 sur Growth, 720 sur Scale | Votre compte, toutes clés confondues, sandbox et live à part |
| API key | La même valeur que le compte | La valeur exacte d'Authorization |
| Endpoint | 30 paiements, 20 transferts, 10 remboursements, 50 clients, multipliés par la valeur de votre plan divisée par 120. Lire un transfert ne compte pas dans la part des transferts | Compte, environnement et endpoint |
| Écritures de payout | 20 | POST /transfers, POST /transfers/batch, POST /accounts/{id}/payouts, POST /beneficiaries, POST /beneficiaries/{id}/receivables et POST /beneficiaries/{id}/receivables/{receivable}/settle, ensemble, par compte et par environnement |
| Vérification de bénéficiaire | 10, et 200 par jour en live | POST /beneficiaries/{id}/verify, par compte et par environnement |
Enterprise n'est pas limité par le plan
Un compte Enterprise n'a aucun plafond de compte, de clé ni d'endpoint. Les plafonds des écritures de payout et de la vérification de bénéficiaire s'appliquent quel que soit le plan, Enterprise compris.
La sandbox et le live sont comptés à part. Chacun dispose de la totalité des plafonds ci-dessus : un test de charge lancé avec une clé sandbox ne consomme jamais la minute de votre checkout live. La ligne API key n'a rien à faire pour cela : une clé sandbox et une clé live sont deux clés.
Lisez la limite, ne la codez pas en dur
Votre quota de compte dépend de votre plan et de tout plafond personnalisé que le support a défini pour vous. Plutôt que de recopier un tableau qui peut changer sans prévenir, relisez-le dans chaque réponse :
X-RateLimit-Limit: 360
X-RateLimit-Remaining: 357
X-RateLimit-Reset: 1748083260X-RateLimit-LimitintegerfacultatifX-RateLimit-RemainingintegerfacultatifX-RateLimit-Resetunix timestampfacultatifCes trois en-têtes ne décrivent que le compteur du compte. Les compteurs par clé, par IP et
par endpoint ne sont pas exposés : un 429 peut donc arriver alors que X-RateLimit-Remaining
semble encore confortable. Le champ type du corps indique lequel s'est déclenché.
Pas d'en-têtes, pas de plafond
Un compte sur un plan illimité ne reçoit aucun en-tête X-RateLimit-*, plutôt qu'un chiffre
fictif. Interprétez leur absence comme « pas de limitation au niveau du compte », jamais comme
zéro.
À quoi ressemble un 429
typestringfacultatifteam (votre compte), api_key, ip (un appel sans clé), endpoint, ou une limite nommée comme payout_writes ou beneficiary_verifications.retry_afterintegerfacultatifRetry-After.retry_after_humanstringfacultatifHH:MM:SS, pour les logs et les tickets de support.Lisez type avant de réagir. Un 429 de type team ou api_key signifie qu'il faut ralentir
partout ; un 429 de type endpoint signifie que seule cette ressource est saturée et que le
reste de votre trafic peut continuer ; un 429 de type ip signifie que l'appel est parti sans
clé.
Depuis un navigateur
Une page qui appelle l'API avec une clé publique peut lire chaque réponse, 429 compris : elle porte
les en-têtes CORS comme toute autre réponse. Le code de la page peut lire Retry-After,
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset et X-Wajub-Version, et attendre
le délai que l'API demande au lieu de le deviner.
Les limitations plus strictes, comme celle des écritures de payout, répondent avec le même corps :
type nomme la limite (payout_writes), et retry_after comme l'en-tête Retry-After donnent
l'attente réelle. Traitez tout 429 de limitation de la même façon : lisez retry_after, attendez,
réessayez.
Un 429 qui n'est pas une limitation
POST /events/{id}/resend répond 429 avec error_code: event_resend_cooldown quand l'événement a
été renvoyé il y a moins de 5 minutes, depuis Konsole ou depuis l'API, à chaque endpoint qui ne l'a
pas accepté. Le corps porte error_code et retry_after au lieu de type, et Retry-After donne
les secondes restantes, jusqu'à 300. Un renvoi avant ce délai obtient la même réponse, tout comme un
client qui réessaie de lui-même un 429 après quelques secondes : renvoyez une fois Retry-After
écoulé.
Attente progressive
Respectez Retry-After quand il est présent, et rabattez-vous sur une attente exponentielle avec
une part d'aléa (jitter) quand il ne l'est pas. Le jitter compte : sans lui, tous les workers
limités à la même seconde réessaient à la même seconde.
async function withRetry(send, max = 3) {
for (let attempt = 0; ; attempt++) {
const res = await send();
if (res.status !== 429 || attempt >= max) return res;
const header = Number(res.headers.get('retry-after'));
const wait = Number.isFinite(header) && header > 0
? header
: 2 ** attempt * (0.5 + Math.random() * 0.5);
await new Promise((r) => setTimeout(r, wait * 1000));
}
}L'exemple PHP réutilise les mêmes $options, donc la même clé d'idempotence : la nouvelle
tentative ne peut pas créer un second paiement. Consultez Idempotence.
Le SDK réessaie déjà
Les SDKs officiels réessaient déjà un 429 pour vous, en respectant Retry-After. N'ajoutez votre propre boucle de nouvelles tentatives qu'autour d'une opération métier complète,
jamais autour de chaque appel.
Lissez vos pics
Les jobs de rapprochement, les exports et les payouts en masse doivent régler leur propre cadence
plutôt que d'envoyer mille requêtes et d'encaisser les 429. Lire X-RateLimit-Remaining et
marquer une pause quand il approche de zéro coûte moins cher que de réessayer, et n'affecte pas
votre trafic interactif.