Aller au contenu

Référence de l’API

Appels, fiches et messages, derrière une seule clé

Une API versionnée pour les parties de Ringfully qu’une intégration a une raison de toucher, avec ses limites énoncées plutôt que sous-entendues.

11 points de terminaison, 5 portées120 requêtes par minute, par cléEn version 1, des champs s’ajoutent, aucun ne disparaît

S’authentifier

Chaque requête porte une clé d’API en jeton de porteur. Les clés s’émettent dans le portail, sous Paramètres, Clés d’API : la clé complète n’apparaît qu’une seule fois, à l’émission, et n’est conservée que sous forme de empreinte. Une clé perdue se remplace, elle ne se récupère pas.

Authorization: Bearer rk_live_…

Une clé appartient à une seule organisation, et l’organisation se déduit de la clé elle-même. Il n’y a aucun identifiant de compte à transmettre, et en transmettre un ne changerait pas l’organisation atteinte.

https://api.ringfully.com/api/v1

Émettre une clé dans le portail

Portées

Une clé est émise avec un sous-ensemble choisi parmi ces cinq portées. Ce qui est appliqué à chaque requête est l’intersection de ce sous-ensemble et de la liste ci-dessous : une clé ne peut donc jamais détenir ce qui n’y figure pas. Interrogez GET /me pour connaître les portées réellement détenues, ce qui permet de distinguer un refus d’une fonction absente.

PortéeAccèsCe qu’elle permet
calls.view.teamLectureLire l’historique des appels.
contacts.viewLectureLire le répertoire.
contacts.manageÉcritureCréer, modifier et supprimer des fiches.
sms.viewLectureLire les conversations texte.
sms.sendÉcritureEnvoyer des messages texte, ce qui est facturé à l’organisation.

Points de terminaison

Onze en tout. Les réponses sont en JSON, les horodatages en ISO 8601 (UTC) et les numéros de téléphone en format E.164, à l’entrée comme à la sortie.

MéthodeCheminPortéeCe qu’elle permet
GET/meÀ qui appartient cette clé, pour quelle organisation, et les portées qu’elle détient vraiment. Le premier appel à faire.
GET/callscalls.view.teamLes appels, du plus récent au plus ancien. Filtrez par sens ou par date de début, puis paginez avec le curseur renvoyé.
GET/calls/:idcalls.view.teamUn appel, par l’identifiant renvoyé dans la liste. C’est notre identifiant, pas celui du transporteur.
GET/contactscontacts.viewLe répertoire partagé. Les numéros vus lors d’un appel sont inclus par défaut; utilisez includeAutoCreated=false pour ne garder que les fiches saisies par une personne.
POST/contactscontacts.manageCréer une fiche. Si l’organisation avait déjà ce numéro en fiche créée automatiquement, cette fiche est nommée plutôt que dupliquée : la réponse est 200 avec adopted à true, et non 201.
GET/contacts/:idcontacts.viewUne fiche.
PATCH/contacts/:idcontacts.manageModifier une fiche. N’importe quel sous-ensemble des champs; un corps vide est refusé, pour qu’un nom de champ mal orthographié ne ressemble pas à une réussite.
DELETE/contacts/:idcontacts.manageSupprimer une fiche. 204 en cas de réussite.
GET/messagessms.viewUne ligne par conversation, activité la plus récente en tête. Les fils sont regroupés par numéro externe pour toute l’organisation.
GET/messages/:counterpartsms.viewLes messages d’une conversation. Les lire ici ne les marque pas comme lus : cela se produit quand une personne ouvre le fil dans le logiciel de téléphonie.
POST/messagessms.sendEnvoyer un message texte au nom de l’organisation. L’envoi est facturé au tarif du transporteur, et un numéro ayant répondu STOP est refusé.

Limites de débit

120 requêtes par minute et par clé, et 600 par minute et par réseau avant même la vérification de la clé. La limite s’applique à la clé plutôt qu’à l’organisation : un traitement par lots qui a besoin de marge reçoit sa propre clé au lieu d’étouffer l’intégration en service. Chaque réponse porte RateLimit-Limit, RateLimit-Remaining et RateLimit-Reset, de sorte qu’un client bien élevé ralentit avant d’être refusé.

Ce que nous nous engageons à ne pas casser

Dans la version 1, des champs peuvent s’ajouter, mais aucun n’est retiré ni renommé. De nouveaux paramètres facultatifs, de nouveaux champs de réponse et de nouveaux points de terminaison peuvent apparaître à tout moment : ignorez les champs que vous ne reconnaissez pas. Tout ce qui retirerait ou renommerait un champ paraîtra en version 2, à une autre adresse.

La spécification lisible par machine

Un document OpenAPI 3.1, produit à partir des mêmes schémas que ceux validés par le code, et servi sans authentification. Vous pouvez y brancher un générateur de client.

https://api.ringfully.com/api/v1/openapi.json

Ouvrir le document OpenAPI

Ce que la version 1 ne couvre pas

Trois choses en sont absentes volontairement, et chacune est un choix, non un rang dans une file.

Le contrôle des appels en cours (garde, transfert, conférence, enregistrement). Cela n’a de sens que pendant l’appel, et il n’existe pas encore de canal en temps réel ici : une intégration ne saurait pas qu’un appel est en cours.

Les enregistrements et l’audio des messages vocaux. C’est ce que nous détenons de plus sensible, et le confier à un identifiant collé dans un outil d’automatisation tiers ne peut pas être le comportement par défaut.

Les utilisateurs, les rôles, la facturation, les numéros, les scénarios d’appel et les paramètres d’urgence. Ils modifient le compte, et une clé divulguée ne doit pas pouvoir inviter quelqu’un, déplacer un numéro ni changer la destination des appels.

Webhooks sortants

Plutôt que d’interroger l’API en boucle, un point de terminaison qui vous appartient peut recevoir les événements. Chaque livraison porte quatre en-têtes, et le corps est signé avec un secret montré une seule fois, à la création du point de terminaison.

X-Ringfully-EventLe nom de l’événement, par exemple call.completed.
X-Ringfully-TimestampMillisecondes depuis l’époque Unix. Utilisez la valeur telle quelle, comme une chaîne opaque, sans la reformater.
X-Ringfully-SignatureHMAC-SHA256 en hexadécimal minuscule sur la charge signée ci-dessous.
X-Ringfully-DeliveryIdentique à chaque nouvelle tentative d’une même livraison. Servez-vous-en comme clé d’idempotence : la livraison est au moins une fois, jamais exactement une fois.

Vérifier une livraison

  1. Lisez X-Ringfully-Timestamp comme une chaîne, exactement telle qu’elle est envoyée.
  2. Prenez le corps brut de la requête, avant toute analyse JSON. Analyser puis resérialiser ne redonne pas les mêmes octets et ne correspondra pas.
  3. Assemblez-les : signedPayload = timestamp + « . » + corps brut.
  4. Calculez le HMAC-SHA256 de cette chaîne avec le secret de votre point de terminaison, en hexadécimal minuscule.
  5. Comparez le résultat à X-Ringfully-Signature avec une comparaison à temps constant.
  6. Rejetez un horodatage à plus de cinq minutes de votre propre horloge. L’étape cinq prouve que le message vient de nous; seule celle-ci prouve qu’il vient d’arriver.

Les livraisons sont réessayées : traitez X-Ringfully-Delivery comme clé d’idempotence et attendez-vous à voir le même événement plus d’une fois.

Nous poser une question sur l’API