Aller au contenu

Vue d'ensemble de l'API

Chaque endpoint REST de RolChat suit un même contrat : la même URL de base, la même enveloppe de réponse, la même pagination, la même forme d’erreur. Apprenez-le une fois et chaque famille d’endpoints de la référence des endpoints se lit de la même façon.

https://api.rolchat.com/api/v1/

La version figure dans le chemin. Ajouter des champs facultatifs, de nouveaux endpoints ou de nouveaux paramètres de requête avec des valeurs par défaut ne constitue pas un changement incompatible et ne change pas la version. Les changements incompatibles sont publiés en v2, et les endpoints v1 dépréciés continuent de fonctionner pendant au moins six mois après leur annonce (voir Dépréciation).

Méthode En-tête Usage
JWT bearer Authorization: Bearer <access_token> Sessions interactives (l’application web, les applications mobiles)
Clé d’API Authorization: Bearer rcp_<secret> Appels de machine à machine, clés d’API de plugins
Signature HMAC X-RolChat-Signature: sha256=… Webhooks entrants depuis vos systèmes, voir Webhooks
Aucune - Endpoints publics du widget (/widget/…, /forms/…), limités par site et par origine

Pour les intégrations, utilisez une clé d’API (un jeton d’accès personnel). Les clés se créent dans Paramètres → Plugins → Clés d’API RolChat, ne sont affichées qu’une fois et ne sont stockées que sous forme de hachage. Une clé ne peut jamais faire plus que le membre qui l’a créée : ses portées sont comparées aux permissions actuelles de ce membre à chaque appel. Voir Authentification pour la durée de vie des JWT, l’en-tête X-Account-Id et les sessions multi-entreprises.

Une ressource unique :

{
"data": { "id": "cnt_01HK…", "email": "ada@example.com" },
"meta": {
"request_id": "req_01HK…"
}
}

Une liste :

{
"data": [ { … }, { … } ],
"meta": {
"request_id": "req_01HK…",
"count": 50,
"next_cursor": "cur_01HK…",
"prev_cursor": "cur_01HK…",
"has_more": true
}
}

Les réponses sans corps (204 No Content après une suppression) portent tout de même l’en-tête X-Request-Id.

Une erreur :

{
"errors": [
{
"code": "validation_failed",
"message": "Email must be valid.",
"field": "email",
"details": { "received": "not-an-email" }
}
],
"meta": { "request_id": "req_01HK…" }
}

code est une valeur lisible par machine en snake_case, sur laquelle baser votre logique ; message est en anglais et destiné aux journaux. field et details sont présents lorsqu’ils sont utiles et ne contiennent jamais de données personnelles. L’API ne répond jamais 200 avec un tableau errors : en présence d’erreurs, le statut est 400 ou plus. La liste complète des codes se trouve sur la page Erreurs.

Les endpoints de liste susceptibles de grossir utilisent la pagination par curseur. Demandez la première page sans curseur, puis renvoyez tel quel le next_cursor reçu :

GET /api/v1/contacts?limit=50
GET /api/v1/contacts?limit=50&cursor=eyJrIjoi…
  • limit vaut 50 par défaut et est plafonné à 200 ; les valeurs supérieures sont rejetées avec 400 validation_failed.
  • Les curseurs sont opaques et expirent après 24 heures (400 validation_failed avec code: cursor_expired).
  • Les résultats sont cohérents avec l’instantané pris à la première page : les fiches supprimées entre deux pages disparaissent, les nouvelles fiches n’apparaissent que lorsque vous recommencez sans curseur.
  • Un en-tête Link avec rel="next" et rel="prev" est également envoyé pour les clients qui le préfèrent.

Envoyez un en-tête Idempotency-Key (un UUID ou un ULID, jusqu’à 255 caractères) avec tout POST, PATCH ou DELETE :

  • La première requête portant une clé s’exécute, et son statut et son corps sont conservés pendant 24 heures.
  • Une répétition avec la même clé et le même corps renvoie la réponse conservée sans réexécuter les effets de bord.
  • Une répétition avec la même clé mais un corps différent est rejetée avec 409 idempotency_key_conflict.

Utilisez-la pour chaque appel qui crée quelque chose avec des effets de bord : envoi d’un message, d’un e-mail ou d’un SMS, passage d’un appel, tout ce qui est facturé. Les requêtes GET sont toujours idempotentes et ignorent l’en-tête.

Les limites sont comptées par minute et calculées par compte, par clé d’API ou par utilisateur (par adresse IP sur les routes qui ne demandent pas de connexion). Les plafonds par défaut :

Seau Limite par défaut Par minute
Requêtes sans connexion (par IP) 60 par IP
Utilisateur connecté (tableau de bord) 1 000 par utilisateur
Clé d’API 1 000 par clé
Endpoints publics du widget 60 par visiteur, et 600 par adresse réseau par minute
Connexion (/auth/login) 5 par IP
Webhooks entrants 300 par minute
Serveur MCP 600 par minute
Endpoints OAuth 600 par minute

Ces plafonds sont les valeurs par défaut de la plateforme et l’opérateur peut les modifier ; votre forfait ne les multiplie pas, et les limites Enterprise sont fixées dans votre contrat. Les endpoints soumis à une limite renvoient :

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 543

Lorsque vous dépassez une limite, la réponse est 429 avec code: rate_limited dans le tableau errors et un en-tête Retry-After en secondes. Attendez ce délai avant l’appel suivant. Dix échecs de connexion verrouillent le compte pendant 30 minutes.

Catégorie Corps de requête maximal Délai d’expiration côté serveur
Par défaut 1 MB 30 s
Message avec pièces jointes 25 MB 30 s
Import CSV 50 MB renvoie 202 et s’exécute en arrière-plan
Images de la base de connaissances 10 MB 30 s
API en masse 10 MB 30 s
Recherche 1 MB 10 s
Requêtes IA 1 MB 60 s
Endpoints du widget 100 KB 30 s

Les corps trop volumineux reçoivent 413 payload_too_large. Un service en amont qui dépasse le délai répond 504 avec code: upstream_timeout et une indication retry_after lorsqu’une nouvelle tentative peut aider.

  • Les requêtes et les réponses sont en application/json; charset=utf-8. Les envois de fichiers utilisent multipart/form-data ; les exports CSV renvoient text/csv. L’UTF-8 invalide est rejeté avec 400 validation_failed.
  • Les horodatages sont au format ISO-8601 en UTC avec une précision à la milliseconde : 2026-04-20T14:23:45.123Z. Tout décalage ISO-8601 est accepté en entrée et normalisé en UTC.
  • Les identifiants sont des ULID ou des UUID opaques. Il n’y a pas d’identifiants numériques, et les adresses e-mail ou numéros de téléphone n’apparaissent jamais dans une URL.

Chaque requête authentifiée s’exécute dans un seul compte. Une ressource qui appartient à un autre compte, ou à un site que le rôle de l’appelant ne couvre pas, renvoie 404 not_found plutôt que 403, afin de ne jamais révéler l’existence de fiches. Un jeton valide sans la permission requise (par exemple contacts.delete) renvoie 403 forbidden. Certaines permissions portent un suffixe de périmètre (conversations.read:own, :team, :all) qui restreint ce que renvoie une liste.

PATCH n’accepte que les champs modifiables. id, account_id, created_at, updated_at et les champs d’état comme resolved_at sont en lecture seule ; en envoyer un renvoie 400 validation_failed avec details.forbidden_fields. Les changements d’état passent par des actions dédiées comme POST /tickets/:id/resolve.

Chaque écriture est enregistrée dans le journal d’audit du compte.

Chaque réponse contient :

X-Request-Id: req_01HK…

Journalisez X-Request-Id. C’est la première chose que demande le support.

L’origine du tableau de bord dans le navigateur est https://app.rolchat.com. Les endpoints publics du widget acceptent toutes les origines, ou uniquement celles que vous vérifiez pour un site. Les appels de serveur à serveur avec une clé d’API ne sont pas soumis à CORS.

  1. Le changement est annoncé dans le journal des modifications et l’endpoint concerné commence à envoyer Deprecation: true et un en-tête Sunset avec la date de retrait.
  2. Les endpoints publics continuent de fonctionner pendant au moins six mois après l’annonce.
  3. Le retrait n’a lieu que dans une nouvelle version majeure. Au sein de v1, les changements sont uniquement additifs.

Chaque service expose /healthz (vivacité) et /readyz (disponibilité).