Skip to content
Langue: Français

API pour les développeurs

Limites de débit : limites et en-têtes

Mis à jour le 1 novembre 2026 6 min de lecture

Combien de requêtes par minute l’API LinkHarbor autorise, quelle taille peut avoir une requête, comment lire les en-têtes et bien gérer un 429.

Pour que l’API reste rapide pour tout le monde, LinkHarbor limite le nombre de requêtes par minute. Les limites ne dépendent pas de votre offre – il n’y a pas de quota mensuel d’appels API. Cet article liste toutes les limites et montre comment votre code peut les gérer proprement.

Comment les requêtes sont comptées

  • Chaque requête tombe dans exactement un compartiment, par exemple user pour les requêtes authentifiées ou token pour l’échange de jeton
  • Le comptage se fait par minute pleine (UTC) ; le compteur repart de zéro à chaque nouvelle minute
  • Selon le compartiment, l’API compte par espace de travail, par personne, par connexion ou par adresse IP
  • Les requêtes qui échouent déjà sur le jeton, la portée ou le schéma (401, 403 insufficient_scope, 400, 422 validation_failed issu du contrôle de schéma) ne comptent pas ; les erreurs ultérieures comme 403 feature_not_available comptent

Toutes les limites

Compartiment (X-RateLimit-Bucket)LimiteCompté parS’applique à
user600 par minuteEspace de travail pour les jetons de clés API (toutes les clés et outils IA de l’espace de travail ensemble) ; personne pour les connexions au tableau de bordToutes les requêtes authentifiées vers /v1 qui n’ont pas leur propre compartiment
token30 par minuteAdresse IPPOST /v1/token
public120 par minuteAdresse IPRequêtes à l’API sans authentification, comme GET /v1/plans et GET /v1/pages/available
callback120 par minuteAdresse IPPOST /v1/callbacks/sale
internal120 par minuteAdresse IPURL d’ingestion de l’intégration « Custom (API) » (POST /v1/ingest/{id})
mcp120 par minuteConnexion IA (jeton d’accès)Serveur MCP sous /mcp
oauth300 par minuteAdresse IPConnexion OAuth et découverte pour les assistants IA
auth30 par minuteAdresse IPConnexion, inscription, réinitialisation du mot de passe (tableau de bord et app)
refresh120 par minuteAdresse IPProlongation d’une session du tableau de bord
discover60 par minutePersonne, adresse IP si non connectéLa rubrique Découvrir de l’app
subs_read120 par minutePersonne, adresse IP si non connectéLecture des pages suivies (app)
subs_write20 par minutePersonne, adresse IP si non connectéModification des pages suivies (app)

Un budget par espace de travail

Tous les jetons issus de clés API d’un même espace de travail se partagent les 600 requêtes par minute – quel que soit le nombre de clés créées. Les outils des assistants IA connectés comptent aussi, car ils appellent l’API en interne. Plus de clés n’augmentent donc pas la limite. Si une forte charge est répartie sur plusieurs programmes, tenez compte du budget partagé.

Les en-têtes

X-RateLimit-Limit
La limite du compartiment par minute, par exemple 600.
X-RateLimit-Remaining
Le nombre de requêtes restantes dans la minute en cours.
X-RateLimit-Bucket
Le compartiment dans lequel la requête est tombée, par exemple user.
Retry-After
Uniquement avec 429 rate_limited : secondes jusqu’au début de la minute suivante. Avec api_key_locked, le temps d’attente figure dans details.retry_after_sec.

Quand la limite est atteinte

Une fois la limite atteinte, l’API répond HTTP 429 avec ce corps ; le texte de message est dans la langue du compte (voir Format et codes d’erreur), ici en anglais, le code rate_limited reste le même :

Réponse en cas de 429
HTTP/1.1 429 Too Many Requests
Retry-After: 37
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 0
X-RateLimit-Bucket: user

{ "error": "rate_limited", "message": "Too many requests. Please try again in a moment.", "retry_after_sec": 37 }
  1. Lisez Retry-After ou retry_after_sec
  2. Attendez au moins ce nombre de secondes, plus un peu d’aléatoire pour que tous les processus ne repartent pas au même moment
  3. Réessayez la requête quelques fois au maximum
  4. Si vous recevez sans cesse 429, étalez le travail sur plus de temps
Node.js : mettre le jeton en cache et gérer le 429
const BASE = 'https://dock.at-harbor.com';
let cached = null; // { token, expiresAt }

async function getToken() {
  if (cached && Date.now() < cached.expiresAt - 60_000) return cached.token;
  const res = await fetch(BASE + '/v1/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      key_id: process.env.LH_KEY_ID,
      key_secret: process.env.LH_KEY_SECRET,
    }),
  });
  if (!res.ok) throw new Error('Token exchange failed: HTTP ' + res.status);
  const data = await res.json();
  cached = { token: data.token, expiresAt: Date.now() + data.expires_in * 1000 };
  return cached.token;
}

async function lh(method, path, body, attempt = 0) {
  const headers = { Authorization: 'Bearer ' + (await getToken()) };
  if (body !== undefined) headers['Content-Type'] = 'application/json';

  const res = await fetch(BASE + path, {
    method,
    headers,
    body: body === undefined ? undefined : JSON.stringify(body),
  });

  if (res.status === 429 && attempt < 3) {
    const wait = Number(res.headers.get('Retry-After') ?? 5);
    await new Promise((r) => setTimeout(r, (wait + Math.random() * 2) * 1000));
    return lh(method, path, body, attempt + 1);
  }
  if (res.status === 401 && attempt === 0) {
    cached = null; // jeton expiré – réessayer une fois avec un nouveau jeton
    return lh(method, path, body, attempt + 1);
  }
  const data = await res.json().catch(() => null);
  if (!res.ok) throw new Error((data && data.error) + ' (HTTP ' + res.status + ')');
  return data;
}

// Exemple : const { items } = await lh('GET', '/v1/pages');

Astuces pour les gros volumes de données

  • Mettez le jeton en cache et ne le renouvelez que peu avant son expiration au bout de 15 minutes
  • Surveillez X-RateLimit-Remaining et ralentissez quand la valeur devient basse
  • Envoyez les requêtes l’une après l’autre plutôt que sur des dizaines de connexions parallèles
  • Chargez les listes une fois et filtrez-les localement au lieu d’interroger chaque page séparément
  • Étalez les grosses synchronisations sur plusieurs minutes
  • Réessayez les erreurs 5xx avec des pauses croissantes, mais pas les erreurs 4xx

Autres limites

QuoiLimiteRéponse
Connexions échouéesVerrouillage après 5, 10 et 20 échecs par adresse e-mail et IP : 60 secondes, 5 minutes, 30 minutes429 account_locked
Envois de formulaire10 par heure et par adresse IP, tous formulaires confondus429 form_rate_limited

Les échecs lors de l’échange de jeton verrouillent temporairement la clé et l’IP, voir Clés API et jetons. Vous n’envoyez les notifications push que dans le tableau de bord ; leurs limites sont expliquées dans Abonnés et notifications push.

Les limites de contenu de votre offre – pages, liens, blocs, liens courts, etc. – ne sont pas des limites de débit mais des plafonds fixes. Elles figurent dans Comparatif des offres.

Taille des requêtes

Chaque corps est mesuré avant que l’API ne le lise. Sa taille maximale dépend de l’endpoint :

EndpointsCorps maximal
Connexion, inscription et les autres appels non authentifiés sous /v1/auth, POST /v1/token, POST /v1/oauth/exchange, les endpoints OAuth des assistants IA sous /oauth et leur consentement, POST /v1/ingest/{id}, le paiement du bloc Soutenir, les appels d’abonnement de l’app (suivi, collections, appareils push), le changement d’espace de travail, POST /v1/auth/logout-all, la suppression d’un compte, la configuration de la double authentification, l’acceptation d’une invitation, l’activation du programme de parrainage et l’étape de retour lors de la connexion d’une intégration64 Ko
Tous les autres endpoints JSON, y compris l’envoi d’un formulaire sur une page1 Mo
POST /v1/webhooks/{id}/verify-signature et le serveur MCP sous /mcp2 Mo
Téléversements de fichiers (POST /v1/assets et POST /v1/pages/{id}/uploads, multipart/form-data)11 Mo pour toute la requête, le fichier lui-même au maximum 10 Mo

Si le corps est plus grand, l’API répond 413 request_too_large ; details.max_bytes et details.max_kb indiquent la limite. Un fichier trop volumineux lors d’un téléversement entraîne 413 payload_too_large. Les endpoints sans corps, comme les appels DELETE, n’acceptent aucun corps ou seulement {}.

Réponse en cas de 413
HTTP/1.1 413 Payload Too Large

{ "error": "request_too_large", "message": "…", "details": { "max_bytes": 65536, "max_kb": 64 }, "request_id": "…" }

Il existe aussi des limites à l’intérieur du corps : chaque texte a une longueur maximale, chaque liste un nombre maximal d’éléments, et les champs inconnus sont refusés. Les valeurs sont listées par endpoint dans la référence de l’API. Une violation entraîne 422 validation_failed, et details nomme le champ, la règle et la limite. Le chemin et la chaîne de requête d’une requête peuvent compter ensemble au maximum 16 Ko.

Vous n’avez rien trouvé ?

Dites-nous ce dont vous avez besoin, et notre équipe support vous aidera personnellement.

Contacter le support