Documentation Développeurs

Connectez vos propres logiciels à votre boîte SyBox

Envoyez des messages WhatsApp depuis votre propre numéro, affichez les données de vos clients à côté de chaque chat, ouvrez des dossiers, recevez chaque événement sur votre propre serveur et ajoutez un chat en direct à votre site web. La route d'envoi utilise le format de l'API WhatsApp Cloud : un code écrit pour Meta n'a besoin que d'une nouvelle URL de base et d'une clé SyBox.

URL de basehttps://api.sybox.io

Premiers pas

Démarrage rapide

Trois éléments pour envoyer votre premier message: l'URL de base, une clé d'appareil et le point de terminaison.

POST/v26.0/{phone-number-id}/messagesAuthorization: Bearer <DEVICE_KEY>

Le segment de version est accepté sous toute forme v<n> (v26.0, v1.0, …) — conservez celle qu'utilise déjà votre code. Le {phone-number-id} est l'identifiant de votre numéro WhatsApp, exactement comme chez Meta.

Le {phone-number-id} est affiché après id sur la carte du numéro, dans Paramètres › Messagerie › Canaux. Une clé d'envoi est liée à un seul numéro et n'envoie que depuis celui-ci.

cURL
curl -X POST https://api.sybox.io/v26.0/PHONE_NUMBER_ID/messages \
  -H "Authorization: Bearer YOUR_DEVICE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "to": "15551234567",
    "type": "text",
    "text": { "body": "Hello from SyBox" }
  }'

La carte de chaque clé, dans Paramètres › Intégrations › Clés API, indique quand elle a été utilisée pour la dernière fois — le moyen le plus rapide de vérifier que vos appels arrivent bien.

Premiers pas

Authentification et clés

Chaque appel transmet une clé dans l'en-tête Authorization, sous forme de jeton Bearer. Chaque clé a un seul rôle : une clé créée pour envoyer ne peut pas ouvrir de dossier, et une clé créée pour ouvrir des dossiers ne peut pas envoyer. Gardez toutes vos clés sur votre serveur — la seule exception est la clé publique du Chat en direct, conçue pour figurer dans vos pages.

HTTP
Authorization: Bearer YOUR_KEY
Content-Type: application/json
CléÀ quoi elle sert
Envoyer via WhatsAppPOST /v{n}/{phone-number-id}/messages
Enregistrer une réclamationPOST /v1/case
Lancer une automatisationPOST /v1/automation
Lire et mettre à jour les contactsPOST /v1/contacts/…
Recevoir d'un programmePOST /v1/inbound
Clé publique · lcpk_<script … data-key="lcpk_…">
Clé de signature pour les utilisateurs connectés · lcid_Utilisateurs connectés : la clé de signature
Clé de serveur (pour votre propre écran de chat) · lcsk_/v1/livechat/*
Clé de signature des réponses · lcwh_x-sybox-signature
Clé de signatureX-Hub-Signature-256

Premiers pas

Obtenir une clé d'appareil

Les clés sont créées dans votre espace de travail.

  1. Ouvrez votre espace de travail → Paramètres → Clés API.
  2. Chaque clé est liée à un seul numéro.
  3. Votre vrai jeton WhatsApp ne quitte jamais notre serveur.
  4. La passerelle est désactivée par défaut.

API WhatsApp

Envoyez votre premier message

Un message texte simple. Le corps est le charge utile standard de l'API Cloud — nous le transmettons tel quel.

POST/v26.0/{phone-number-id}/messagesAuthorization: Bearer <DEVICE_KEY>
curl -X POST https://api.sybox.io/v26.0/PHONE_NUMBER_ID/messages \
  -H "Authorization: Bearer YOUR_DEVICE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "to": "15551234567",
    "type": "text",
    "text": { "body": "Hello from SyBox" }
  }'

La réponse

Vous recevez exactement ce que Meta renvoie, avec le même statut HTTP.

200 OK · application/json
{
  "messaging_product": "whatsapp",
  "contacts": [{ "input": "15551234567", "wa_id": "15551234567" }],
  "messages": [{ "id": "wamid.HBgLMTU1NTEyMzQ1NjcVAgARGBI…" }]
}

API WhatsApp

Tous les types de messages sont pris en charge

Modèles, images, documents, messages interactifs. Voici un exemple d'envoi de modèle.

{
  "messaging_product": "whatsapp",
  "to": "15551234567",
  "type": "template",
  "template": {
    "name": "order_shipped",
    "language": { "code": "en_US" },
    "components": [{
      "type": "body",
      "parameters": [{ "type": "text", "text": "#10432" }]
    }]
  }
}

Un texte libre ne parvient à un client que dans les 24 heures qui suivent son dernier message. En dehors de cette fenêtre, envoyez un modèle approuvé : SyBox refuse alors le texte libre avec le code 131047 avant qu'il n'atteigne Meta.

API WhatsApp

Règles et limites des clés

Chaque clé d'envoi a ses propres règles, définies à sa création : texte libre, modèles ou les deux ; médias ou non ; quels modèles ; quels pays de destination ; les heures d'envoi autorisées ; et une limite quotidienne. Un envoi qui enfreint l'une d'elles est refusé par SyBox avant d'atteindre Meta.

StatutQuand
404Une réponse vide : la Passerelle API est désactivée, ou la clé n'appartient à aucun espace de travail. Vérifiez l'interrupteur en haut de Paramètres › Intégrations › Clés API.
401La clé est absente ou inconnue.
403La clé n'est pas une clé d'envoi, ou elle envoie depuis un numéro auquel elle n'est pas liée.
403Le message enfreint l'une des règles de la clé : texte libre, modèles, médias, nom du modèle, pays ou heures.
403Meta a mis le modèle en pause, ou l'a limité en raison de son évaluation de qualité.
400La fenêtre de 24 heures est fermée (code 131047) : envoyez plutôt un modèle.
400Le corps n'est pas un JSON valide, ou le numéro WhatsApp de la clé n'est plus connecté.
409Meta a temporairement bloqué l'envoi depuis ce numéro.
429La limite quotidienne de la clé, ou la limite de messagerie WhatsApp du numéro, est atteinte.
502Impossible de joindre Meta. Réessayez.

Le compteur quotidien repart à zéro à minuit UTC, et un envoi qui échoue n'est pas compté.

API WhatsApp

Gestion des erreurs

Les erreurs viennent de deux sources, et toutes deux utilisent le format d'erreur de Meta : un client existant de l'API Cloud les lit donc sans modification. Une erreur de Meta est renvoyée exactement telle que Meta l'a envoyée, avec le code de statut de Meta. Une erreur issue d'une règle propre à SyBox a le type SyBoxGatewayError, et son message indique quelle règle a refusé l'appel.

{
  "error": {
    "message": "(#131030) Recipient phone number not in allowed list",
    "type": "OAuthException",
    "code": 131030
  }
}

Votre système dans SyBox

Affichez vos données à côté de la conversation

À l'ouverture d'une conversation, SyBox appelle VOTRE point de terminaison et affiche votre réponse juste à côté du chat — commandes, solde, tickets du client. Nous envoyons le téléphone du client, ou son e-mail pour une conversation par e-mail.

Ajoutez votre point de terminaison dans Paramètres › Intégrations › API ERP. Chaque appel est un POST avec votre clé dans Authorization et la requête dans un seul champ, data, qui contient une chaîne JSON — ainsi, chaque côté peut ajouter des champs plus tard sans casser l'autre. Répondez en moins de 15 secondes.

POST YOUR_ERP_URL
Authorization: Bearer YOUR_ERP_KEY
X-Sybox-Action: lookup
X-Sybox-Lang: en
X-Sybox-Theme: light
X-Sybox-Agent: 6f1c…
X-Sybox-Number: 104857600000000
Content-Type: application/json

{ "data": "{\"phone\":\"15551234567\",\"email\":\"customer@example.com\",\"ref\":\"\"}" }

Chaque appel indique aussi qui fait la demande : X-Sybox-Lang (la langue de l'utilisateur — répondez dans cette langue), X-Sybox-Theme (light ou dark, pour une réponse html), X-Sybox-Agent (l'identifiant de l'utilisateur) et X-Sybox-Number (la ligne sur laquelle se trouve la conversation).

Nous envoyons le téléphone et l'e-mail — l'un peut être vide ; faites la correspondance avec celui qui identifie le client dans votre système, et répondez avec { renderAs, content }.

renderAs

Définissez renderAs pour indiquer à SyBox comment afficher vos données — l'une de :

renderAsDescription
tableDes lignes et des colonnes. content est un tableau d'objets plats (ou { rows: [ … ] }) ; leurs clés deviennent les en-têtes des colonnes.
cards · kpiDe petites tuiles, comme un solde ou un nombre de commandes. content est un tableau de { label, value } (ou { cards: [ … ] }).
feed · list · threadUne chronologie de cartes. content est un tableau de { title, text, date, tags, media: [{ type, url, name }] }.
messageUn enregistrement présenté sous la forme d'une seule carte, à la manière d'un message.
htmlVotre propre HTML, sous forme de chaîne dans content. Uniquement pour un balisage que vous générez vous-même.
sectionsPlusieurs blocs dans une seule réponse : content est { sections: [ { title, renderAs, content } ] }.
jsonLa valeur par défaut lorsque renderAs est omis : SyBox affiche votre content sous forme de JSON mis en forme.

Ajoutez un sybox_ref à une ligne de tableau ou une carte pour la rendre cliquable — SyBox vous rappelle avec ce ref afin que vous renvoyiez le détail de cet enregistrement.

Recherche de produits (X-Sybox-Action: products)

Le même point de terminaison peut également répondre aux recherches de produits. L'utilisateur saisit ce que demande le client, SyBox l'envoie en tant que « q », et votre réponse s'affiche sous forme de fiches produits à côté du chat — avec un bouton d'envoi en un clic qui insère le lien du produit dans la zone de saisie.

POST YOUR_ERP_URL
Authorization: Bearer YOUR_ERP_KEY
X-Sybox-Action: products

# the decoded "data":
{ "q": "wireless keyboard", "phone": "15551234567", "email": "customer@example.com", "ref": "" }
ChampDescription
nameobligatoireLe seul champ obligatoire. Un produit réduit à son nom donne quand même une fiche propre.
price · oldPrice · currencyDes nombres, pas des chaînes formatées. N'envoyez oldPrice que s'il existe un vrai prix précédent — la remise est calculée à partir des deux.
available · stockavailable vaut true/false ; stock est un compteur facultatif affiché à côté. Omettez-les si vous ne suivez pas le stock — un champ absent n'affiche rien et n'est jamais lu comme « rupture ».
imageUne URL d'image https directe. Une image qui ne charge pas laisse place à un fond neutre.
linkL'URL de la fiche produit. Sans elle, la carte est en lecture seule — Envoyer n'apparaît que s'il y a quelque chose à envoyer.
noteUne courte ligne libre sous le prix — délai de livraison, variante, condition.

Rien de plus que l'endpoint déjà en place : même URL, même clé, même enveloppe { "data": "…" }. Lisez X-Sybox-Action pour distinguer une recherche produit d'une recherche client. Répondez avec content sous forme de tableau (ou { items: [ … ] }).

Votre système dans SyBox

Créer un dossier depuis votre propre système

C'est la route utilisée par un ERP ou système comptable pour ouvrir un ticket ou dossier dans SyBox CRM.

POST/v1/caseAuthorization: Bearer <CASE_KEY>
curl -X POST https://api.sybox.io/v1/case \
  -H "Authorization: Bearer $SYBOX_CASE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_unique_id": "CUST-10432",
    "header": "Screen replacement not delivered",
    "description": "Paid on 12 Aug, promised in 3 days, still nothing.",
    "department_id": 5,
    "ext_ref": "TICKET-99817"
  }'

Les champs

ChampDescription
customer_unique_idVotre propre identifiant du client — la même clé que celle de la synchronisation des clients. Envoyez plutôt phone si vous n'avez pas d'identifiant.
phoneLe numéro de téléphone du client, si vous n'avez pas d'identifiant.
header · descriptionAu moins un est requis. L'en-tête est la ligne que les utilisateurs voient dans la liste.
department_idobligatoireintegerObligatoire. Le département auquel le dossier est attribué : le numéro affiché à côté dans Paramètres › Départements (par exemple #5).
ext_refVotre numéro de ticket.
sectionintegerDe 1 à 4 : l'onglet de dossiers dans lequel il est placé. 1 par défaut.
deadlinestringUne date d'échéance, YYYY-MM-DD.
notifybooleantrue par défaut : une note avec le numéro du dossier apparaît dans la conversation du client dans SyBox. Rien n'est envoyé au client. Avec false, la note n'est pas ajoutée.
sourcestringLe nom du programme affiché sur cette note. ERP par défaut.

La réponse contient le numéro du dossier, celui que votre équipe communique au client. Une nouvelle tentative avec le même ext_ref répond "duplicate": true avec le dossier qui existe déjà, sans customer_id.

Le client doit déjà exister dans SyBox. Si l'identifiant est introuvable, SyBox lance une synchronisation des clients avec votre système, puis cherche à nouveau ; s'il reste introuvable, la réponse est 404 — jamais un dossier ouvert au nom d'un client inventé.

Utilisez une clé de type 'case'.

Votre système dans SyBox

Injecter un message depuis un autre programme

Pour tout ce qui n'est pas WhatsApp: une note de caisse, une alerte d'appareil.

POST/v1/inboundAuthorization: Bearer <INBOUND_KEY>

Ce type de clé n'est plus créé : une clé Recevoir d'un programme existante continue de fonctionner. Pour une nouvelle intégration, ouvrez un dossier — SyBox écrit la note dans la conversation pour vous.

cURL
curl -X POST https://api.sybox.io/v1/inbound \
  -H "Authorization: Bearer $SYBOX_INBOUND_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "15551234567",
    "text": "Order 4821 has left the warehouse.",
    "source": "Warehouse"
  }'
ChampDescription
phoneobligatoirestringLe numéro de téléphone du client, avec l'indicatif du pays.
textobligatoirestringLe message.
sourcestringLe nom du programme, affiché sur le message.

La réponse est {"ok": 1, "id": …}, l'identifiant de la note dans la conversation.

Entrant uniquement, par conception.

Votre système dans SyBox

Contacts : lire et mettre à jour

Avec une clé de type Lire et mettre à jour les contacts, un programme peut rechercher un contact, le lire et modifier son nom, son e-mail, ses champs de contact et ses libellés. Chaque appel est un POST avec un corps JSON.

La clé agit au nom de la personne qui l'a créée : elle ne trouve que les contacts que cette personne est autorisée à voir, et uniquement si elle peut ouvrir la liste des contacts et voir les numéros. Pour modifier quoi que ce soit, cette personne doit être autorisée à modifier les contacts. Une clé dont le créateur est désactivé cesse de fonctionner.

POST/v1/contacts/searchAuthorization: Bearer <CONTACTS_KEY>

Recherche les contacts dont le nom, le téléphone ou l'e-mail contient q. limit vaut 20 par défaut, 50 au maximum.

POST/v1/contacts/get

Un contact, par phone ou par key (le même contact.key envoyé par un webhook).

POST/v1/contacts/update

Ne modifie que ce que vous envoyez : name, email et fields (champs de contact par identifiant ou par nom, avec leurs valeurs ; une valeur vide efface le champ).

POST/v1/contacts/labels

Ajoute et retire des libellés par identifiant ou par nom : add et remove sont des listes.

curl -X POST https://api.sybox.io/v1/contacts/update \
  -H "Authorization: Bearer $SYBOX_CONTACTS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "201112223344",
    "name": "Sara Ali",
    "fields": { "city": "Alexandria" }
  }'

# Find:   POST /v1/contacts/search  {"q": "sara", "limit": 20}
# Read:   POST /v1/contacts/get     {"phone": "201112223344"}
# Labels: POST /v1/contacts/labels  {"phone": "201112223344", "add": ["VIP"], "remove": [7]}

Chaque appel renvoie le contact (search : une liste de contacts) : key, name, phone, email, channel, labels et fields.

Événements

Webhooks : les événements sur votre serveur

Ajoutez votre point de terminaison dans Paramètres › Intégrations › Webhooks, choisissez les événements et les numéros, et SyBox y envoie chaque événement en POST au moment où il se produit. Un événement WhatsApp arrive au format webhook de Meta : un gestionnaire écrit pour Meta fonctionne sans modification.

ÉvénementDescription
messageMessage entrantUn message d'un client.
statusStatut du messageEnvoyé, distribué, lu ou échoué — pour un message que vous avez envoyé.
reactionRéactionUn client a réagi à un message.
doneConversation marquée comme terminéeUne conversation a été marquée comme terminée : par une personne, par une automatisation ou automatiquement après le silence du client.
labelLibellé ajouté ou retiréUn libellé a été ajouté à une conversation ou retiré de celle-ci.
contactContact créé ou mis à jourUn contact a été créé, ou son nom, son e-mail ou ses champs de contact ont changé.
dealAffaire conclueUne affaire conclue a été enregistrée dans une conversation.
caseDossier CRM ouvert ou ferméUn dossier CRM a été ouvert ou fermé (résolu, non résolu ou annulé).
Requête · SyBox → vous
POST YOUR_WEBHOOK_URL
Content-Type: application/json
X-Hub-Signature-256: sha256=5d1f0c…
x-sybox-signature: sha256=5d1f0c…
x-sybox-event: message
x-sybox-timestamp: 1761400000

{
  "object": "whatsapp_business_account",
  "entry": [{
    "id": "WABA_ID",
    "changes": [{
      "field": "messages",
      "value": {
        "messaging_product": "whatsapp",
        "metadata": { "display_phone_number": "15550001111", "phone_number_id": "PHONE_NUMBER_ID" },
        "contacts": [{ "profile": { "name": "Sara" }, "wa_id": "15551234567" }],
        "messages": [{
          "from": "15551234567",
          "id": "wamid.HBgLMTU1NTEyMzQ1NjcVAgASGBQ…",
          "timestamp": "1761400000",
          "type": "text",
          "text": { "body": "Is my order shipped?" }
        }]
      }
    }]
  }]
}

Médias. Le lien propre à Meta nécessite un jeton Meta pour s'ouvrir : SyBox le remplace donc par un lien signé vers sa propre copie du fichier, valable 24 heures. Un message vocal peut aussi contenir sa transcription dans sybox.transcription, lorsque le webhook la demande.

Les autres canaux — Messenger, Instagram, Telegram et Chat en direct — arrivent au format propre à SyBox, uniquement pour l'événement message :

JSON
{
  "object": "sybox",
  "event": "message",
  "channel": "telegram",
  "line": "8123456789",
  "workspace": "yourworkspace",
  "contact": { "key": "tg:6423115118", "name": "Sara" },
  "message": {
    "id": "812345",
    "timestamp": 1761400000,
    "type": "image",
    "text": "",
    "caption": "The broken part",
    "media": { "url": "https://api.sybox.io/…", "mime": "image/jpeg" }
  }
}

Les événements de conversation arrivent au format propre à SyBox, pour chaque canal. event indique exactement ce qui s'est passé :

Événement<code>event</code>
Conversation marquée comme terminéeconversation.done
Libellé ajouté ou retirélabel.added · label.removed
Contact créé ou mis à jourcontact.created · contact.updated
Affaire concluedeal.closed
Dossier CRM ouvert ou fermécase.opened · case.closed
Événement de testtest
{
  "object": "sybox",
  "event": "conversation.done",
  "channel": "whatsapp",
  "line": "201001234567",
  "workspace": "yourworkspace",
  "timestamp": 1761400000,
  "contact": {
    "key": "201112223344",
    "name": "Sara",
    "phone": "201112223344",
    "email": "",
    "channel": "whatsapp",
    "labels": [{ "id": 3, "name": "VIP" }],
    "fields": [{ "id": 2, "key": "city", "name": "City", "value": "Cairo" }]
  },
  "data": { "by": "Omar", "note": "Refund sent" }
}

Clé de signature

En-têteDescription
X-Hub-Signature-256sha256= suivi du HMAC-SHA256 en hexadécimal du corps brut, calculé avec le secret de signature du webhook — le même en-tête et la même méthode que chez Meta.
x-sybox-signatureLa même valeur, pour qu'un point de terminaison qui reçoit aussi les appels de Meta puisse distinguer les nôtres.
x-sybox-eventCe qui s'est passé : message, status, reaction, l'un des événements de conversation ci-dessous (conversation.done, label.added…) ou test.
x-sybox-timestampLa date d'envoi, en secondes Unix.
x-sybox-signature-rsaUne seconde signature : rsa-sha256= suivi du RSA-SHA256 (PKCS#1 v1.5) en base64 de x-sybox-timestamp, d'un point et du corps brut.
x-sybox-key-idLaquelle de nos clés l'a produite. La clé publique se trouve à l'adresse https://api.sybox.io/.well-known/sybox-webhook-key.

Vérifiez la signature sur les octets bruts, avant de les analyser, et comparez en temps constant :

const crypto = require('crypto');

// express.raw: the signature is over the bytes as sent, so read them before any JSON parser.
app.post('/sybox/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sent = Buffer.from(req.get('X-Hub-Signature-256') || '');
  const want = Buffer.from('sha256=' + crypto
    .createHmac('sha256', process.env.SYBOX_WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex'));
  if (sent.length !== want.length || !crypto.timingSafeEqual(sent, want)) return res.sendStatus(401);

  res.sendStatus(200);                       // answer first, then do the work
  const event = JSON.parse(req.body);
  const kind = req.get('x-sybox-event');     // message | status | reaction
});

Vous préférez ne pas conserver de secret partagé sur votre serveur ? Vérifiez plutôt x-sybox-signature-rsa avec notre clé publique. Dans les deux cas, refusez un horodatage de plus de cinq minutes.

Répondez avec n'importe quel code 2xx en moins de 15 secondes. Toute autre réponse — une erreur, un délai dépassé, une redirection — entraîne une nouvelle tentative après 1, 2, 4, 8, 16 et 32 minutes, puis l'événement est abandonné. Un événement peut arriver plusieurs fois : utilisez l'identifiant du message pour ignorer un doublon. L'adresse doit être publique et en https.

Un webhook qui échoue 20 fois de suite pendant plus d'une heure est désactivé automatiquement et l'administrateur de l'espace de travail est prévenu. Ses événements en attente sont conservés pendant 24 heures : réactivez-le pour les envoyer.

Pour tester, cliquez sur Envoyer un événement de test sur la carte du webhook. Livraisons, sur la même carte, affiche les 50 dernières livraisons avec la réponse de votre serveur et permet d'en renvoyer une.

Chat en direct

Chat en direct

Ajoutez un chat à votre site web : les visiteurs y écrivent, votre équipe répond dans SyBox. Ajoutez le site dans Paramètres › Messagerie › Canaux, sur la carte Chat en direct ; la fenêtre qui s'ouvre, Code pour votre site, vous donne le code et les clés ci-dessous. Les trois clés secrètes ne sont affichées qu'une seule fois.

CléCommence parÀ quoi elle sert
Clé publiquelcpk_Se place dans vos pages. Elle peut être publiée sans risque : elle ne fait que désigner le site, et le chat ne s'affiche que sur vos Adresses de sites web.
Clé de signature pour les utilisateurs connectéslcid_Sur votre serveur uniquement. Signe chaque utilisateur connecté, pour que personne ne puisse écrire au nom d'un autre.
Clé de serveur (pour votre propre écran de chat)lcsk_Sur votre serveur uniquement. Seulement pour un site qui crée son propre écran de chat au lieu du chat prêt à l'emploi.
Clé de signature des réponseslcwh_Sur votre serveur uniquement. Prouve qu'une réponse envoyée à votre serveur vient bien de SyBox.

Le chat prêt à l'emploi n'a besoin que du code. La clé de signature sert à un site avec des comptes ; la clé de serveur et la clé de signature des réponses, uniquement à un site qui a son propre écran de chat.

Désactiver un site web masque immédiatement le chat. Les appels de votre serveur restent acceptés et enregistrés.

Ajouter le chat à votre site

Collez le code une fois dans chaque page, juste avant la balise de fermeture body. Le chat ne s'affiche que sur les adresses indiquées dans Adresses de sites web, et sa couleur, sa position, son titre et son message d'accueil se règlent dans SyBox, pas dans le code.

HTML
<script async src="https://api.sybox.io/lc/w.js" data-key="lcpk_YOUR_PUBLIC_KEY"></script>

WordPress : téléchargez notre extension depuis la même fenêtre. Shopify : dans l'application Shopify de SyBox, activez Chat en direct sur cette boutique, puis SyBox Live Chat sous Intégrations d'applications — un client connecté est reconnu sans rien faire de plus.

Utilisateurs connectés : la clé de signature

Lorsqu'un utilisateur est connecté à votre site, votre serveur indique au chat qui il est grâce à un jeton court — un JWT, HS256 — signé avec la clé de signature. L'utilisateur a alors une seule conversation à son nom, sur tous ses appareils, et personne ne peut l'ouvrir en saisissant l'identifiant de quelqu'un d'autre.

  1. Après la connexion, votre serveur crée le jeton à partir des claims ci-dessous.
  2. La page le transmet au chat sous la forme identity, avant le code du chat.
  3. Après une connexion sans rechargement de la page, appelez plutôt SyBoxChat('identify', token).
ChampDescription
subobligatoirestringL'identifiant de votre utilisateur, jusqu'à 120 caractères. Il ne doit pas commencer par v_.
expobligatoirenumberExpiration, en secondes Unix — pas plus d'un jour à l'avance. Dix minutes suffisent : le jeton n'est lu qu'à l'ouverture du chat.
namestringLe nom affiché dans la conversation.
emailstringL'adresse e-mail de l'utilisateur.
phonestringLe numéro de téléphone de l'utilisateur.
picturestringUne adresse https de la photo de l'utilisateur, jusqu'à 500 caractères. SyBox en garde sa propre copie, et la récupère à nouveau à la connexion suivante si l'adresse change.
function b64url(string $s): string { return rtrim(strtr(base64_encode($s), '+/', '-_'), '='); }

$header  = b64url(json_encode(['alg' => 'HS256', 'typ' => 'JWT']));
$payload = b64url(json_encode([
    'sub'   => (string) $user->id,
    'name'  => $user->name,
    'email' => $user->email,
    'exp'   => time() + 600,          // ten minutes
]));
$signature = b64url(hash_hmac('sha256', "$header.$payload", getenv('SYBOX_LC_SIGNING_KEY'), true));
$token = "$header.$payload.$signature";
HTML
<script>
  window.SyBoxChatConfig = { identity: "TOKEN_FROM_YOUR_SERVER", locale: "en" };
</script>
<script async src="https://api.sybox.io/lc/w.js" data-key="lcpk_YOUR_PUBLIC_KEY"></script>

Créez le jeton sur votre serveur uniquement. Une clé de signature dans une page web permet à n'importe qui d'écrire au nom de n'importe lequel de vos utilisateurs. Et ne mettez jamais un simple identifiant d'utilisateur dans la page à la place du jeton : n'importe qui pourrait alors choisir la conversation à lire.

Lorsque Uniquement les utilisateurs connectés à mon site est activé, un visiteur sans jeton ne voit pas le chat.

Un visiteur qui a discuté avant de se connecter se voit demander une seule fois, dans le même navigateur, s'il veut poursuivre cette conversation avec son compte. Vous n'avez rien à faire pour cela.

Contrôler le chat depuis votre page

Le code du chat ajoute une fonction à votre page, SyBoxChat :

JavaScript
SyBoxChat('open');                       // open the chat
SyBoxChat('close');                      // close it
SyBoxChat('identify', token);            // after a sign-in without a page reload
SyBoxChat('locale', 'fr');               // the chat's language
SyBoxChat('on', 'message', function (m) {
  // a reply arrived
});
SyBoxChat('on', 'open', function () { /* the chat opened */ });
SyBoxChat('on', 'close', function () { /* the chat closed */ });

// Before the chat's code, every setting is optional:
window.SyBoxChatConfig = {
  identity: 'TOKEN_FROM_YOUR_SERVER',    // a signed-in user (see above)
  name: 'Sara', email: 'sara@example.com', // a visitor without an account: fills the form for them
  locale: 'ar',
  serviceWorker: 'auto'                   // 'auto' | '/your-sw.js' | 'site' | 'off'
};

Notifications après la fermeture de votre site

Tant qu'une page de votre site est ouverte, une réponse s'affiche d'elle-même en notification. Pour joindre un visiteur après la fermeture de votre site, les navigateurs exigent un service worker sur votre propre domaine : servez cette seule ligne sous /sybox-lc-sw.js à la racine de votre site, en application/javascript.

/sybox-lc-sw.js
try { importScripts('https://api.sybox.io/lc/sw.js'); } catch (e) {}

Choisissez le mode dans SyBox (Notifications quand le site est fermé) ou dans la page avec serviceWorker : "auto" (le fichier ci-dessus, par défaut), un chemin de votre choix, "site" (placez la même ligne en haut de votre propre service worker) ou "off".

Le chat ne remplace jamais un service worker que votre site possède déjà, et le fichier n'a pas de gestionnaire fetch : il ne voit donc jamais aucune requête de votre site. L'extension WordPress sert le fichier pour vous. Safari sur iPhone n'affiche aucune notification pour un simple site web.

Votre propre écran de chat : la clé de serveur

Un site ou une application qui a son propre écran de chat communique avec SyBox depuis son serveur au lieu d'utiliser le chat prêt à l'emploi. Chaque appel transmet Authorization: Bearer lcsk_…. Votre serveur désigne l'utilisateur par votre propre identifiant, et SyBox lui fait confiance, car il détient la clé.

AppelDescription
POST /v1/livechat/messagesVotre utilisateur écrit. client_id rend une nouvelle tentative sans risque : un même identifiant n'est enregistré qu'une fois ("duplicate": 1).
POST /v1/livechat/uploadUn fichier, en données de formulaire multipart : file, user_id, client_id. Jusqu'à 16 Mo : images, messages vocaux, vidéos, PDF, texte et documents Office.
GET /v1/livechat/messages?user_id=&since=&before=&limit=La conversation : les messages après since, et agents_read_id, le plus récent des messages de votre utilisateur lu par un agent.
POST /v1/livechat/readVotre utilisateur a lu les réponses jusqu'à up_to.
POST /v1/livechat/editVotre utilisateur modifie son propre message, dans les 15 minutes.
POST /v1/livechat/deleteVotre utilisateur supprime son propre message pour tout le monde, dans les 24 heures.
POST /v1/livechat/reactUne réaction sur n'importe quel message ; un emoji vide la retire.
POST /v1/livechat/typingVotre utilisateur est en train d'écrire : envoyez on: 1 toutes les quelques secondes et on: 0 quand il s'arrête.
curl -X POST https://api.sybox.io/v1/livechat/messages \
  -H "Authorization: Bearer $SYBOX_LC_SERVER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "user":    { "id": "u42", "name": "Sara Ali", "email": "sara@example.com", "locale": "ar" },
    "message": { "client_id": "a1b2c3", "text": "Hi, is my order on its way?", "reply_to": "" }
  }'

Un message, dans l'historique et dans les réponses :

JSON
{
  "id": 990,
  "guid": "b81d…",
  "dir": "out",                       // "in" = your user wrote it, "out" = your team
  "type": "image",                    // text | image | audio | video | file
  "text": "Here is the tracking page",
  "media": { "url": "https://api.sybox.io/…", "mime": "image/png", "name": "tracking.png", "w": 1080, "h": 720 },
                                       // a voice note or a video also has "secs"
  "status": 3,                         // on your user's messages: 1 received, 3 read by an agent
  "reply_to": "7c9e…",
  "client": "a1b2c3",                  // on your user's messages: the client_id you sent
  "react_us": "",                      // your team's reaction on it
  "react_me": "👍",                    // your user's reaction on it
  "at": "2026-10-25T09:41:07Z",
  "edited": 0
}

L'historique d'un utilisateur qui n'a jamais écrit répond 404 unknown_user : affichez une conversation vide.

Les liens des médias sont signés et valables une heure ; redemandez-en un nouveau. SyBox ne récupère jamais un fichier depuis une adresse que vous envoyez : téléversez-le. Jusqu'à 120 appels par minute et par site web.

Les réponses sur votre serveur : la clé de signature des réponses

Saisissez l'Adresse de votre serveur pour les réponses sur le site web. Lorsque votre équipe répond, modifie, supprime ou lit, SyBox y envoie l'événement en POST, signé avec la clé de signature des réponses.

En-têteDescription
x-sybox-signaturet=TIMESTAMP,v1=SIGNATURE — TIMESTAMP en secondes Unix, SIGNATURE le HMAC-SHA256 en hexadécimal de TIMESTAMP.BODY (le corps brut), calculé avec la clé de signature des réponses.
x-sybox-eventmessage.created, message.updated, message.deleted ou messages.read.
x-sybox-deliveryIdentique à chaque nouvelle tentative d'un même événement : utilisez-le pour ignorer un doublon.

Le corps contient event, line_id, user_id et message — ou message_id pour une suppression, et read_id pour messages.read : les messages de votre utilisateur sont lus jusqu'à cet identifiant.

const crypto = require('crypto');

app.post('/sybox/livechat', express.raw({ type: 'application/json' }), (req, res) => {
  const parts = Object.fromEntries((req.get('x-sybox-signature') || '').split(',').map(p => p.split('=')));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return res.sendStatus(401);   // older than five minutes

  const want = Buffer.from(crypto.createHmac('sha256', process.env.SYBOX_LC_REPLY_KEY)
    .update(t + '.').update(req.body).digest('hex'));
  const sent = Buffer.from(parts.v1 || '');
  if (sent.length !== want.length || !crypto.timingSafeEqual(sent, want)) return res.sendStatus(401);

  res.sendStatus(200);
  const delivery = req.get('x-sybox-delivery');   // seen it already? ignore
  const evt = JSON.parse(req.body);               // { event, line_id, user_id, message | message_id | read_id }
});

Vérifiez la signature sur le corps brut, refusez un t de plus de cinq minutes, et répondez rapidement par un 2xx. Toute autre réponse entraîne une nouvelle tentative après 10 s, 30 s, 2 min, 10 min et 30 min, puis l'événement est abandonné. SyBox n'appelle que des adresses publiques et ne suit jamais de redirection.

Codes de motif

Chaque réponse du Chat en direct est en JSON — {"ok": 1, …}, ou {"ok": 0, "error": "CODE"} avec un code plutôt qu'une phrase :

CodeStatutDescription
unauthorized401La clé de serveur est incorrecte ou a été remplacée.
invalid_json invalid_payload invalid_user_id400La requête n'a pas le format attendu.
empty_message no_file empty_file400Ni texte ni fichier.
too_long400Le texte modifié dépasse 4 096 caractères.
not_an_emoji400emoji n'est pas un emoji.
not_found404Ce message n'existe pas, ou il n'appartient pas à cet utilisateur.
too_late409Le délai pour modifier ou supprimer est dépassé.
file_type_not_allowed400Ce type de fichier n'est pas accepté.
file_too_large413Le fichier dépasse 16 Mo.
blocked403Votre équipe a bloqué cet utilisateur.
unknown_user404Aucune conversation pour cet identifiant d'utilisateur pour l'instant.
rate_limited429Trop d'appels : ralentissez et réessayez.
maintenance503SyBox est en cours de mise à jour : réessayez après Retry-After secondes.
server_error500Une erreur s'est produite de notre côté.

Remplacer une clé

Vous avez perdu une clé, ou pensez qu'elle a fuité ? Sur la fiche du site web, cliquez sur Nouvelle clé de signature, Nouvelle clé de serveur ou Nouvelle clé de signature des réponses. Une nouvelle clé de serveur laisse l'ancienne fonctionner pendant un jour, pour que vous puissiez basculer sans interruption ; les autres clés cessent de fonctionner immédiatement.