Limites de débit

Quotas de requêtes par jeton sur l'API REST Qyvo et le serveur MCP, et comment gérer les réponses 429.

Qyvo applique un quota de requêtes par jeton sur l'API REST et le serveur MCP. La valeur par défaut est généreuse pour un usage normal ; les intégrations à fort volume devraient prévoir un backoff.

Quota

Surface Limite par défaut Fenêtre En-têtes exposés
/api/v1/* 120 req / jeton 60 s glissantes X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After (sur 429)
/mcp 300 ops / jeton 60 s glissantes Idem

Le quota compte chaque requête authentifiée, y compris les pings sans effet.

Les limites peuvent être relevées au cas par cas pour les intégrations en production. Envoyez un email à [email protected] avec le nom de votre jeton et le débit attendu.

Lecture des en-têtes

Chaque réponse réussie inclut :

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117

Lorsque Remaining atteint 0, la requête suivante renvoie 429 Too Many Requests :

HTTP/1.1 429 Too Many Requests
Retry-After: 23

Retry-After est le nombre de secondes à attendre avant de réessayer.

Gestion du 429 dans le code

Un simple wrapper de backoff exponentiel gère proprement la limitation transitoire. Respectez toujours Retry-After s'il est présent.

async function callQyvo(url, init = {}, attempt = 0) {
  const res = await fetch(url, {
    ...init,
    headers: {
      Authorization: `Bearer ${process.env.QYVO_TOKEN}`,
      ...(init.headers || {}),
    },
  });

  if (res.status === 429 && attempt < 5) {
    const wait = Number(res.headers.get('Retry-After') ?? 2) * 1000;
    await new Promise((r) => setTimeout(r, wait));
    return callQyvo(url, init, attempt + 1);
  }

  return res;
}
use Illuminate\Support\Facades\Http;

$response = Http::withToken(env('QYVO_TOKEN'))
    ->retry(5, 0, function (\Throwable $e, $request) {
        if ($e instanceof \Illuminate\Http\Client\RequestException
            && $e->response->status() === 429) {
            $wait = (int) ($e->response->header('Retry-After') ?? 2);
            sleep($wait);
            return true;
        }
        return false;
    })
    ->get('https://www.qyvo.io/api/v1/me');
import os, time, httpx

def call_qyvo(method, url, **kwargs):
    headers = kwargs.pop('headers', {})
    headers['Authorization'] = f"Bearer {os.environ['QYVO_TOKEN']}"
    for attempt in range(5):
        r = httpx.request(method, url, headers=headers, **kwargs)
        if r.status_code != 429:
            return r
        time.sleep(int(r.headers.get('Retry-After', '2')))
    r.raise_for_status()

Conseils pour les envois en masse

L'envoi de broadcasts à des milliers de contacts passe par le flux Broadcasts dans Qyvo, et non par des appels bruts à send-template-message. Les broadcasts sont dispatchés via une file interne qui respecte le palier de débit par numéro de Meta et évite les tempêtes de limites de débit — voir le tableau de bord ou l'outil MCP create_broadcast.

Si vous devez vraiment envoyer un volume élevé depuis votre propre code :

  • Plafonnez la concurrence à 5 requêtes simultanées par jeton
  • Cadencez à au plus 30 envois par seconde (le palier par numéro de Meta peut être plus bas)
  • Utilisez un backoff exponentiel sur 429 et 5xx

Limites que nous n'imposons pas encore

  • Pas de quota quotidien sur les jetons
  • Pas de plafond sur la taille du corps de requête au-delà des limites propres aux templates Meta
  • Pas de plafond de bande passante sur les lectures d'inbox

Elles pourraient être ajoutées plus tard — nous l'annoncerons dans le changelog au moins 30 jours avant activation.