Aller au contenu
Chargement des API keys…

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éePlafond par tranche de 60 secondesCompté par
Non authentifié30IP appelante, seulement pour un appel sans clé
CompteVotre plan : 120 sur Pay as you go, 360 sur Growth, 720 sur ScaleVotre compte, toutes clés confondues, sandbox et live à part
API keyLa même valeur que le compteLa valeur exacte d'Authorization
Endpoint30 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 transfertsCompte, environnement et endpoint
Écritures de payout20POST /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éficiaire10, et 200 par jour en livePOST /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 :

En-têtes de réponse
X-RateLimit-Limit: 360
X-RateLimit-Remaining: 357
X-RateLimit-Reset: 1748083260
X-RateLimit-Limitintegerfacultatif
Le plafond de votre compte pour la fenêtre de 60 secondes en cours.
X-RateLimit-Remainingintegerfacultatif
Requêtes restantes dans cette fenêtre avant que la limite du compte ne se déclenche.
X-RateLimit-Resetunix timestampfacultatif
Moment où le compteur du compte repart de zéro : la fin de la fenêtre en cours, la même valeur à chaque appel de cette fenêtre.

Ces 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

Réponse · 429 Too Many Requests
{
"code": 429,
"status": "Too Many Requests",
"message": "Too many requests",
"type": "team",
"retry_after": 42,
"retry_after_human": "00:00:42"
}
typestringfacultatif
Le limiteur qui s'est déclenché : team (votre compte), api_key, ip (un appel sans clé), endpoint, ou une limite nommée comme payout_writes ou beneficiary_verifications.
retry_afterintegerfacultatif
Nombre de secondes à attendre. Également envoyé dans l'en-tête Retry-After.
retry_after_humanstringfacultatif
Le même délai au format HH: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.

Réponse · 429 sur une écriture de payout
{
"code": 429,
"status": "Too Many Requests",
"message": "Too many requests",
"type": "payout_writes",
"retry_after": 17,
"retry_after_human": "00:00:17"
}

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é.

Réponse · 429 sur un renvoi dans son délai
{
"code": 429,
"status": "Too Many Requests",
"error_code": "event_resend_cooldown",
"message": "This event was resent less than 5 minutes ago to the endpoints that have not accepted it. Retry after the delay in Retry-After.",
"retry_after": 180
}

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.

Que pensez-vous de ce contenu ?