Messages et conversations
L’API Messages vous permet d’envoyer un message à n’importe quel contact, de relire une conversation, de corriger ou de supprimer un message déjà envoyé, d’y réagir, de récupérer l’intégralité d’un fil de discussion, d’exporter une transcription et de marquer des discussions comme lues ou non lues — tout cela sans ouvrir la boîte de réception.
Tous les chemins sur cette page sont relatifs à l’URL de base https://api.youraiconnector.com/v1. Chaque requête nécessite votre clé API — consultez Authentification pour obtenir la liste complète des méthodes pour l’envoyer. Les exemples ci-dessous utilisent l’en-tête X-API-Key, avec un exemple cURL montrant également le formulaire de requête ?apiKey=.
Fonctionnement de la livraison : L’envoi d’un message n’attend pas qu’il soit arrivé à destination. L’API accepte votre message, renvoie immédiatement un identifiant de message, puis le livre en arrière-plan sur le canal du contact (WhatsApp, SMS, Instagram, etc.). Pour savoir si un message a réellement été livré ou lu, écoutez les mises à jour de statut avec les Webhooks — ne faites pas de polling. La réponse d’envoi confirme uniquement que le message a été accepté.
Envoyer un message
Il existe deux façons d’envoyer un message. Choisissez celle qui correspond à la manière dont vous identifiez déjà le contact :
- Envoyer par ID de contact — vous connaissez déjà l’ID du contact (par exemple, vous avez créé le contact via l’API ou l’avez obtenu via un webhook). Utilisez
POST /contacts/{contactId}/send-message. - Envoyer par identité de contact — vous connaissez le numéro de téléphone, l’identifiant Instagram, etc. du contact, mais pas son ID interne. Utilisez
POST /contacts/sendet laissez la plateforme trouver le bon contact.
Les deux méthodes mettent le message en file d’attente de la même manière et le livrent sur le canal utilisé par le contact. Vous ne choisissez pas le transport — la plateforme achemine les contacts WhatsApp via WhatsApp, les contacts SMS via SMS, et ainsi de suite.
Les deux ne trouvent également que les contacts qui existent déjà. Aucun des deux appels n’en crée un : un identifiant ou une identité qui ne correspond à rien renvoie 404, cela ne devient pas un nouveau contact. Donc, si vous envoyez un message à quelqu’un pour la première fois, créez d’abord le contact avec POST /contacts, ou, sur WhatsApp Web, utilisez Envoyer directement à un numéro WhatsApp Web ci-dessous, qui crée le contact lors du même appel.
Envoyer par ID de contact
POST /contacts/{contactId}/send-message
| Champ | Requis | Description |
|---|---|---|
body |
Oui | Le texte du message à envoyer, jusqu’à 65 536 caractères. Un corps de message plus long que ce que le canal autorise en un seul message (1 500 sur l’API WhatsApp Business et SMS, 1 000 sur Instagram, 2 000 sur Messenger, 4 096 sur Telegram et LinkedIn, 5 000 sur LINE, 6 000 sur TikTok, 7 000 sur Viber, 65 536 sur WhatsApp Web ; aucune limite pour l’e-mail, le widget de chat et les canaux personnalisés) est envoyé sous forme de plusieurs messages successifs, divisés par paragraphes ou par phrases. La réponse contient alors messageIds pour chaque partie et autoSplit: true. |
mediaUrl |
Non | URL d’un fichier multimédia (image, audio, vidéo, document) à joindre. |
mediaContentType |
Non | Type MIME du média joint, par ex. image/jpeg. Déduit de l’extension de fichier de l’URL si omis (.mp3 → audio/mpeg, .pdf → application/pdf) ; définissez-le pour une URL sans extension. |
sendAsVoiceNote |
Non | WhatsApp Web uniquement, audio uniquement : envoie l’audio sous forme de note vocale (la bulle de lecture). L’audio qui n’est pas au format OGG/Opus est converti au moment de l’envoi. La valeur par défaut est false. |
pauseBot |
Non | true met l’IA en pause pour ce contact lors de l’envoi du message — pour une prise en main par un humain. Voir Suspendre ou reprendre l’IA. |
clearIncompleteReply |
Non | true ignore une réponse du bot en cours de rédaction afin qu’elle ne reprenne pas après votre message. |
human_reply |
Non | true marque le message comme étant écrit par une personne de votre équipe plutôt que par une intégration. L’IA le traite alors comme une réponse d’un membre de l’équipe dans la conversation, et une réponse que l’IA avait mise en file d’attente pour le dernier message du contact est annulée afin que le contact ne reçoive pas deux réponses. Cela ne met pas l’IA en pause ; utilisez pauseBot pour cela. La valeur par défaut est false. |
Sur LinkedIn, un message envoyé de cette manière, ou depuis la boîte de réception, est délivré même lorsqu’une personne gère la discussion du côté de LinkedIn. Les propres réponses de l’IA et ses suivis sont mis en attente sur une telle discussion. Une réponse mise en attente est supprimée de la discussion plutôt que d’être affichée comme ayant échoué, car rien n’a été envoyé et aucun crédit n’est utilisé. La dernière réponse de l’IA avant qu’elle ne transfère une discussion à une personne est tout de même délivrée.
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/send-message" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"body": "Hi! Your appointment is confirmed for tomorrow at 10:00."
}'
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/send-message",
{
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
body: "Hi! Your appointment is confirmed for tomorrow at 10:00.",
}),
}
);
const data = await res.json();
console.log(data.messageId);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/contact123/send-message",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={"body": "Hi! Your appointment is confirmed for tomorrow at 10:00."},
)
print(res.json()["messageId"])
Réponse (200 OK) :
{
"success": true,
"messageId": "aB3dE5fG7hI9jK1lM2nO",
"contactId": "contact123",
"channel": "whatsapp",
"message": "Message created successfully. Delivery is being processed."
}
Envoyer par identité de contact
POST /contacts/send
Utilisez cette méthode lorsque vous ne disposez pas de l’ID interne du contact. Fournissez le body du message ainsi que soit un contact_id, soit un channel accompagné du champ d’identité correspondant à ce canal.
| Champ | Requis | Description |
|---|---|---|
body |
Oui | Le texte du message à envoyer, jusqu’à 65 536 caractères. Un corps de message plus long que ce que le canal autorise en un seul message (1 500 sur l’API WhatsApp Business et SMS, 1 000 sur Instagram, 2 000 sur Messenger, 4 096 sur Telegram et LinkedIn, 5 000 sur LINE, 6 000 sur TikTok, 7 000 sur Viber, 65 536 sur WhatsApp Web ; aucune limite pour l’e-mail, le widget de chat et les canaux personnalisés) est envoyé sous forme de plusieurs messages dans l’ordre, divisés au niveau des paragraphes ou des phrases. La réponse contient alors messageIds pour chaque partie et autoSplit: true. |
contact_id |
Non | ID d’un contact existant. Lorsqu’il est défini, les champs d’identité ci-dessous ne sont pas nécessaires. |
channel |
Non | Canal sur lequel envoyer. Requis lorsque contact_id n’est pas fourni. L’un des 14 canaux d’envoi sortant : whatsapp, whatsapp_web, sms, instagram, instagram_private, messenger, telegram, chat-widget, custom, email, line, imessage, linkedin, viber. |
phone_number |
Non | Numéro de téléphone du contact au format international. Utilisé avec whatsapp, whatsapp_web et sms. |
instagram_id |
Non | ID utilisateur Instagram du contact. Utilisé avec instagram. |
messenger_id |
Non | ID utilisateur Messenger du contact. Utilisé avec messenger. |
telegram_user_id |
Non | ID utilisateur Telegram du contact. Utilisé avec telegram. |
media_url |
Non | URL d’un fichier multimédia à joindre. |
media_content_type |
Non | Type MIME du média joint, par ex. image/jpeg. |
Quels canaux peuvent être résolus par identité. Seuls six des 14 acceptent un champ d’identité au lieu d’un contact_id : whatsapp, whatsapp_web et sms sont recherchés par phone_number, instagram par instagram_id, messenger par messenger_id, et telegram par telegram_user_id. Les huit autres — instagram_private, chat-widget, custom, email, line, imessage, linkedin et viber — n’ont pas d’identité publique à rechercher, donc l’envoi sur ces canaux nécessite contact_id ; passer channel seul renvoie une 400 vous indiquant que contact_id est requis.
cURL (utilisant le formulaire de requête ?apiKey=)
curl -X POST "https://api.youraiconnector.com/v1/contacts/send?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"channel": "whatsapp",
"phone_number": "+31612345678",
"body": "Hi! Your appointment is confirmed."
}'
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/contacts/send", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
channel: "whatsapp",
phone_number: "+31612345678",
body: "Hi! Your appointment is confirmed.",
}),
});
const data = await res.json();
console.log(data.message_id, data.channel);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/send",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"channel": "whatsapp",
"phone_number": "+31612345678",
"body": "Hi! Your appointment is confirmed.",
},
)
data = res.json()
print(data["message_id"], data["channel"])
Réponse (201 Created) :
{
"success": true,
"message_id": "aB3dE5fG7hI9jK1lM2nO",
"contact_id": "contact123",
"channel": "whatsapp"
}
Pourquoi un message peut être rejeté : Un contact ayant activé le mode « ne pas déranger » ou le mode privé ne peut pas recevoir de messages sortants — la requête échoue avec une erreur
422. Si aucun contact ne correspond à l’ID ou à l’identité que vous avez fourni(e), vous recevrez une erreur404.
Envoi sur WhatsApp Web : variantes et protection contre les envois en rafale
Deux points s’appliquent à body lorsque le contact utilise WhatsApp Web.
Les accolades de spintax sont développées à chaque envoi. Un body de {Hi|Hello|Hey} there, quick question est envoyé sous la forme de l’une des trois salutations, choisie pour cet envoi — les accolades n’atteignent jamais le contact. Utilisez-les pour proposer à chaque contact un message d’ouverture différent à partir du même code d’intégration. Le texte sans accolades est envoyé exactement tel qu’il est écrit.
Les rafales de messages d’ouverture identiques sont refusées. Si dix messages d’ouverture quasi identiques sont envoyés depuis un même numéro WhatsApp Web en l’espace d’une heure à des contacts qui ne vous ont jamais écrit, les suivants ne seront pas distribués : l’envoi est accepté comme d’habitude (vous recevez toujours un messageId), puis le message reste avec status: "failed" et error_code: "opener_burst", accompagné d’une raison lisible par le client. Réessayer avec le même texte ne sert à rien : variez le texte, attendez une heure et renvoyez. Les réponses au sein de conversations existantes ne sont jamais affectées. La raison est expliquée dans Identical openers get numbers restricted.
Envoyer directement à un numéro WhatsApp Web
POST /whatsapp-web/send
Envoyez un message à un numéro de téléphone sur WhatsApp Web sans avoir à rechercher le contact au préalable. Si le numéro n’est pas encore un contact, celui-ci est créé lors du même appel, avec l’IA désactivée pour ce contact, afin que le message apparaisse comme envoyé manuellement et qu’aucun assistant ne prenne le relais par la suite. Un contact existant est réutilisé tel quel.
| Champ | Requis | Description |
|---|---|---|
phoneNumber |
Oui | Le numéro à contacter, au format international (+31612345678). |
message |
Non | Le texte à envoyer. Soit message, soit mediaUrl doit être présent. |
mediaUrl |
Non | URL publique d’un fichier à envoyer. Soit message, soit mediaUrl doit être présent. |
mediaContentType |
Non | Type MIME de ce fichier, par exemple image/jpeg. Déterminé à partir de l’URL si vous ne le précisez pas. |
sendAsVoiceNote |
Non | true envoie un fichier audio en tant que note vocale plutôt qu’en tant que pièce jointe. |
fromPhoneNumber |
Non | Lequel de vos numéros WhatsApp Web connectés utiliser pour l’envoi, au format international. Par défaut, le numéro auquel le contact appartient déjà. |
campaignId |
Non | Utiliser les heures d’activité de cet Agent au lieu de celles par défaut du compte. Doit être un Agent du même compte. |
ignoreActiveHours |
Non | true envoie immédiatement, quelles que soient les heures d’activité. |
sub_account_id |
Non | Pour les agences : envoyer au nom de l’un de vos comptes clients. |
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-web/send?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+31612345678",
"message": "Hi Alex, your quote is ready."
}'
Un appel réussi répond 202 :
{ "success": true, "queued": true, "contactId": "abc123" }
202 signifie accepté, mais pas encore livré. En dehors des heures d’activité, l’envoi est mis en attente et partira lors du prochain créneau autorisé, sauf si vous avez transmis ignoreActiveHours. Lisez le statut du message lui-même avec Lister les messages d’un contact en utilisant le contactId que vous avez obtenu ici.
Lorsque l’envoi échoue :
| Statut | Code | Ce qui s’est passé |
|---|---|---|
400 |
INVALID_PHONE_FORMAT |
Le numéro n’est pas au format international, ou phoneNumber est manquant, ou les deux message et mediaUrl le sont. |
400 |
CONTACT_DND |
Ce contact est en mode Ne pas déranger, donc aucun message sortant ne lui est envoyé. |
400 |
CONTACT_PRIVATE |
Ce contact est marqué comme privé. |
404 |
CAMPAIGN_NOT_FOUND |
Aucun Agent ne correspond au campaignId que vous avez transmis. |
403 |
CAMPAIGN_FORBIDDEN |
Cet Agent appartient à un autre compte. |
402 |
Le compte n’a plus de crédits, ou aucun numéro WhatsApp Web n’est connecté. |
Un second appel pour le même contact alors qu’un envoi est toujours en attente répond 409, afin qu’une file d’attente ne s’accumule jamais derrière une seule personne.
Enregistrer une note dans une conversation
POST /contacts/notes
Ajoute une ligne à la conversation d’un contact sans l’envoyer. Utilisez cette fonction pour ajouter du contexte dont votre équipe et l’IA doivent disposer, mais que le contact ne doit jamais voir : un résumé d’un appel téléphonique que votre agent vocal vient d’effectuer, une remarque provenant de votre CRM ou une note d’un collègue. Cela fonctionne sur tous les canaux (WhatsApp, SMS, Instagram, Messenger, Telegram, le widget de chat, les canaux personnalisés, etc.).
Ce qu’il advient d’une note :
- Elle apparaît dans le chat de la boîte de réception sous la forme d’une carte Note jaune, avec le nom de l’auteur si vous en avez indiqué un.
- L’IA la lit comme faisant partie de l’historique de la conversation, marquée comme note interne, afin que sa prochaine réponse en tienne compte.
- Elle n’est jamais envoyée au contact, ne coûte aucun crédit de message et ne déclenche rien : pas de réponse de l’IA, pas d’automatisation, pas de webhook, pas de notification, pas de badge de message non lu. Elle ne met pas l’IA en pause et ne compte pas comme une réponse de votre équipe.
Trouvez le contact de la même manière que pour Envoyer par identité de contact : soit par son ID, soit par un channel suivi de l’identifiant correspondant. Une note ne peut être ajoutée qu’à un contact existant ; si rien ne correspond, cela renvoie une erreur 404.
| Champ | Requis | Description |
|---|---|---|
contact_id |
L’un des deux | L’identifiant du contact. |
channel + identifier |
L’un des deux | channel plus phone_number (WhatsApp, WhatsApp Web, SMS), instagram_id, messenger_id ou telegram_user_id, comme dans Envoyer par identité de contact. |
body |
Oui | Le texte de la note, jusqu’à 4 000 caractères. Les sauts de ligne sont conservés. |
author |
Non | Qui ou quoi l’a écrit, jusqu’à 80 caractères, par exemple Voice agent ou Sarah (sales). Affiché sur la fiche et pour l’IA. |
timestamp |
Non | Quand cela s’est produit, en millisecondes d’époque. Par défaut, maintenant. Utilisez l’heure de fin de l’appel pour que la note soit placée au bon endroit dans le fil de discussion. Elle ne peut pas être à plus de 5 minutes dans le futur ; une heure ultérieure est rejetée avec une erreur 400. |
external_id |
Non | Votre propre identifiant pour cette note, jusqu’à 200 caractères, par exemple l’identifiant de l’appel. Envoyer le même external_id pour le même contact à nouveau n’ajoute pas une seconde note ; la réponse contient alors duplicate: true. Utilisez-le pour qu’un webhook relancé ne puisse pas enregistrer le même appel deux fois. |
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/notes" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"channel": "whatsapp",
"phone_number": "+31612345678",
"author": "Voice agent",
"body": "Voice call, 3:12. Asked about knee surgery waiting times, prefers a call back on Tuesday morning.",
"external_id": "call_8f2k1"
}'
Réponse (201, ou 200 avec duplicate: true si la external_id a déjà été enregistrée)
{
"success": true,
"messageId": "note_4c1f0e...",
"contactId": "contact123"
}
Une note apparaît dans Lister les messages d’un contact avec type: "note".
Générer un brouillon de réponse avec l’IA
POST /contacts/{contactId}/draft-reply
Demande à l’agent IA qui gère une conversation de rédiger la réponse suivante et vous renvoie le texte. Rien n’est envoyé. Il s’agit du même brouillon que celui généré par le bouton Générer une réponse dans la boîte de réception : l’agent utilise sa configuration, sa base de connaissances et l’historique de la conversation pour répondre dans la langue du contact. Utilisez cette fonction pour placer un humain (ou votre propre application) entre l’IA et le contact : récupérez le brouillon, soumettez-le à approbation, puis envoyez-le avec Envoyer par ID de contact, tel quel ou modifié.
- Le brouillon est rédigé par l’agent affecté au contact. Un contact qui n’a pas encore d’agent se voit attribuer l’agent qui répondrait à son prochain message.
- Lors de la rédaction du brouillon, l’agent n’exécute aucun outil ni aucune fonction ; aucune réservation, aucun ajout de tag, aucun transfert ni aucune autre action n’est effectué.
- Rien n’est enregistré dans la conversation et le contact ne voit rien.
- Un brouillon coûte le même nombre de crédits qu’une réponse IA de cet agent dans cette conversation, et rien si votre propre clé IA est connectée.
- La conversation doit contenir au moins un message.
Tous les champs du corps de la requête sont facultatifs ; un corps vide (ou l’absence de corps) génère le brouillon de la réponse suivante.
| Champ | Requis | Description |
|---|---|---|
instruction |
Non | Une instruction ponctuelle pour ce brouillon, jusqu’à 2 000 caractères, identique à l’action d’appuyer longuement sur « Générer une réponse » dans la boîte de réception. Par exemple Offer Tuesday at 3pm ou Ask for their email address. |
campaign_id |
Non | Rédiger sous cette campagne au lieu de l’agent du contact. |
purpose |
Non | chat_reply (par défaut) rédige un message au contact. faq_answer rédige une courte réponse à la question du contact qui fonctionne de manière autonome, pour une FAQ de base de connaissances. |
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/draft-reply" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "instruction": "Offer Tuesday at 3pm for the consultation" }'
Réponse (200)
{
"success": true,
"contact_id": "contact123",
"draft": "Hi Sara, Tuesday at 3pm works for the consultation. Shall I put you down for it?"
}
Une erreur 400 signifie que la conversation ne contient pas encore de messages, que vos crédits sont épuisés ou que le contact n’a pas d’agent ou de campagne à partir duquel rédiger un brouillon (error indique lequel). Une erreur 404 signifie que le contact n’existe pas ou que la clé d’un membre de l’équipe est limitée aux contacts qu’il ne peut pas voir. La clé ou le membre de l’équipe doit disposer de l’autorisation de modifier les messages.
Vous utilisez un client IA via MCP ? La même action est disponible en tant qu’outil
generate_reply_draft.
Lister les messages d’un contact
GET /contacts/{contactId}/messages
Renvoie les messages d’un contact, du plus récent au plus ancien, avec une pagination basée sur un curseur.
| Paramètre de requête | Requis | Description |
|---|---|---|
limit |
Non | Taille de la page. Par défaut 50, maximum 100. |
cursor |
Non | La valeur next_cursor issue d’une réponse précédente. Renvoie les messages antérieurs au curseur. |
filter |
Non | Filtrer par type de contenu : all (par défaut), text, media ou tool_use. |
direction |
Non | Filtrer par direction : all (par défaut), inbound (reçu du contact) ou outbound (envoyé par vous). |
Remarque sur le filtrage et la pagination : Les filtres
filteretdirectionsont appliqués à chaque page après sa lecture ; une page filtrée peut donc contenir moins d’éléments quelimit. Lenext_cursorcontinue de progresser dans la conversation complète, donc continuez la pagination jusqu’à ce quenext_cursorsoitnull.
cURL
curl "https://api.youraiconnector.com/v1/contacts/contact123/messages?limit=50&direction=inbound" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ limit: "50", direction: "inbound" });
const res = await fetch(
`https://api.youraiconnector.com/v1/contacts/contact123/messages?${params}`,
{ headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.messages, data.next_cursor);
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/contacts/contact123/messages",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"limit": 50, "direction": "inbound"},
)
data = res.json()
print(data["messages"], data["next_cursor"])
Réponse (200 OK) :
{
"success": true,
"contact_id": "contact123",
"messages": [
{
"id": "aB3dE5fG7hI9jK1lM2nO",
"body": "Hi! Thanks for reaching out.",
"direction": "inbound",
"channel": "whatsapp",
"status": "delivered",
"type": null,
"timestamp": "2026-06-01T10:00:00.000Z",
"media_url": null,
"media_content_type": null,
"bot_reply": false
}
],
"next_cursor": "cD4eF6gH8iJ0kL2mN3oP"
}
Champs de message
| Champ | Description |
|---|---|
id |
ID unique du message. |
body |
Contenu textuel du message. Pour un message avec une pièce jointe, body commence par une note entre crochets indiquant ce qui a été reçu, suivie de toute légende, par exemple [THE CONTACT UPLOADED AN IMAGE] Here is my CV ou [THE CONTACT UPLOADED A VOICE NOTE] - [TRANSCRIPTION: ...]. Les notes vocales et les vidéos incluent la transcription. |
direction |
inbound (reçu du contact) ou outbound (envoyé par votre compte). |
channel |
Canal sur lequel le message a été envoyé ou reçu (par ex. whatsapp, sms, instagram). |
status |
État de livraison actuel, par ex. Created, sent, delivered, read, failed. |
type |
Type de message. Les messages en texte brut ont un type null ; l’activité des outils d’assistance automatisés est marquée tool_use. |
timestamp |
Heure de création du message au format ISO 8601. |
media_url |
URL d’un fichier multimédia joint, le cas échéant. Ce lien cesse de fonctionner 7 jours après l’arrivée du message, sur tous les canaux (WhatsApp Business API, WhatsApp Web, Instagram, Messenger, Telegram, widget de chat et autres). Obtenez-en un nouveau avec Télécharger la pièce jointe d’un message. |
media_content_type |
Type MIME du média joint, le cas échéant. |
bot_reply |
true lorsque le message a été généré par l’assistant IA. |
score |
Votre évaluation du message : 1 pouce levé, -1 pouce baissé, 0 lorsqu’il n’a pas été évalué. Voir Évaluer ou mettre en favori un message. |
is_important |
true lorsque le message a été mis en favori. |
is_deleted |
true lorsque le message a été supprimé. Les messages supprimés restent dans la liste mais leurs champs body et media_url sont vides. |
reactions |
Réactions par émojis sur le message, des deux côtés. Toujours un tableau — vide lorsqu’il n’y en a pas. Chaque entrée possède emoji, from_phone_number, from_me (true lorsque la réaction est la vôtre) et reacted_at. |
faq_ids_used |
ID des FAQ de la base de connaissances dont l’IA disposait lorsqu’elle a rédigé cette réponse : celles sélectionnées pour le dernier message plus celles conservées plus tôt dans la conversation. La même liste figure sur chaque message d’une réponse envoyée en plusieurs parties. Toujours un tableau, vide pour les messages entrants, les messages envoyés par des personnes, les suivis automatiques et les réponses de l’IA envoyées avant le 25 septembre 2026. |
faqs_used |
Les mêmes FAQ avec leur question : chaque entrée possède id et question. question est null lorsque la FAQ a été supprimée depuis. |
Télécharger la pièce jointe d’un message
POST /chat-exports/media/download-url
Vous fournit un nouveau lien de téléchargement pour le fichier joint à un message : une image, un message vocal, une vidéo ou un document. Le lien est valide pendant 1 heure. Utilisez-le lorsque vous souhaitez enregistrer des pièces jointes ailleurs (par exemple, pour archiver des CV ou des messages vocaux envoyés par un contact), ou lorsque le media_url sur un message ou un webhook de nouveau message ne s’ouvre plus.
Pour trouver des messages avec des pièces jointes, listez les messages d’un contact avec filter=media. Le id de chaque message et l’ID du contact constituent le messagePath.
| Champ du corps | Requis | Description |
|---|---|---|
messagePath |
Oui | Quel message, sous la forme contacts/{contactId}/messages/{messageId}. |
cURL
curl -X POST "https://api.youraiconnector.com/v1/chat-exports/media/download-url" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"messagePath": "contacts/contact123/messages/aB3dE5fG7hI9jK1lM2nO"}'
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/chat-exports/media/download-url", {
method: "POST",
headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({ messagePath: "contacts/contact123/messages/aB3dE5fG7hI9jK1lM2nO" }),
});
const { data } = await res.json();
console.log(data.url); // download the file within the hour
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/chat-exports/media/download-url",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"messagePath": "contacts/contact123/messages/aB3dE5fG7hI9jK1lM2nO"},
)
file_url = res.json()["data"]["url"]
Réponse (200 OK) :
{
"success": true,
"data": {
"url": "https://storage.googleapis.com/...",
"expiresInMs": 3600000
}
}
| Champ | Description |
|---|---|
data.url |
Le lien de téléchargement. Récupérez le fichier directement à partir de celui-ci, aucune clé API n’est nécessaire. |
data.expiresInMs |
Durée de validité du lien, en millisecondes (3600000 = 1 heure). Appelez à nouveau le point de terminaison pour obtenir un nouveau lien. |
| Statut | Quand |
|---|---|
400 |
messagePath est manquant ou n’est pas sous la forme contacts/{contactId}/messages/{messageId}, ou le message ne contient aucune pièce jointe pouvant être téléchargée de cette manière. Certaines anciennes pièces jointes sont stockées chez le fournisseur de canal et ne peuvent pas être réémises, et un reel ou une publication Instagram partagé est un lien vers Instagram plutôt qu’un fichier. |
403 |
Le contact n’appartient pas à votre compte. |
404 |
Aucun message avec cet identifiant n’existe pour ce contact. |
Vous utilisez un client IA via MCP ? La même action est disponible en tant qu’outil
get_chat_media_download_url.
Lister les sessions de discussion
Une session de chat est une fenêtre de conversation unique avec un contact. Elle s’ouvre lors du premier message entrant lorsqu’aucune session n’est active, et elle se ferme automatiquement 48 heures après le dernier message entrant du contact (chaque nouveau message entrant repousse la fermeture de 48 heures supplémentaires). L’IA qui conclut un chat ne ferme pas la session ; elle déclenche uniquement le webhook Chat Concluded. Les sessions permettent de paginer un long historique en conversations lisibles plutôt que d’avoir une liste interminable.
Sessions récentes pour tous les contacts
GET /chat-sessions/recent
Renvoie les sessions qui ont commencé au cours des X dernières heures, de la plus récente à la plus ancienne, pour chaque contact du compte.
| Paramètre de requête | Requis | Description |
|---|---|---|
hours |
Oui | Combien d’heures remonter en arrière. Doit être un nombre entier positif. |
status |
Non | Ne renvoyer que les sessions avec ce statut : ChatSessionOpened ou ChatSessionClosed. |
limit |
Non | Nombre maximum de sessions à renvoyer. Par défaut 100, maximum 100. |
includeMessages |
Non | true ajoute un tableau messages à chaque session. Désactivé par défaut car cela alourdit considérablement la réponse. |
cURL
curl "https://api.youraiconnector.com/v1/chat-sessions/recent?hours=24&status=ChatSessionClosed" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ hours: "24", status: "ChatSessionClosed" });
const res = await fetch(`https://api.youraiconnector.com/v1/chat-sessions/recent?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.data.total_sessions, data.data.sessions);
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/chat-sessions/recent",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"hours": 24, "status": "ChatSessionClosed"},
)
data = res.json()["data"]
print(data["total_sessions"], data["sessions"])
Réponse (200 OK) :
{
"success": true,
"data": {
"hours_ago": 24,
"total_sessions": 2,
"sessions": [
{
"session_id": "session456",
"contact_id": "contact123",
"contact_name": "Jane Doe",
"contact_phone": "+31612345678",
"contact_email": "jane@example.com",
"start_date_time": "2026-06-01T09:55:00.000Z",
"end_date_time": "2026-06-01T10:20:00.000Z",
"status": "ChatSessionClosed",
"tag": "Booking enquiry"
}
]
}
}
Toutes les sessions pour un contact
GET /chat-sessions/{contactId}
Renvoie toutes les sessions de discussion pour un seul contact. Mêmes paramètres status, limit et includeMessages que ci-dessus — hours ne s’applique pas ici.
cURL
curl "https://api.youraiconnector.com/v1/chat-sessions/contact123?limit=20" \
-H "X-API-Key: YOUR_API_KEY"
Réponse (200 OK) :
{
"success": true,
"data": {
"contact_id": "contact123",
"contact_name": "Jane Doe",
"total_sessions": 2,
"sessions": [
{
"id": "session456",
"start_date_time": "2026-06-01T09:55:00.000Z",
"end_date_time": "2026-06-01T10:20:00.000Z",
"status": "ChatSessionClosed",
"tag": "Booking enquiry"
}
]
}
}
Les noms des champs d’ID de session diffèrent entre les deux points de terminaison. La liste des sessions récentes l’appelle
session_id(elle contient également les détails du contact, car les sessions proviennent de nombreux contacts) ; la liste par contact l’appelleid. L’une ou l’autre valeur est ce que vous transmettez en tant que{sessionId}lors de la récupération du fil complet ci-dessous.
Lorsque includeMessages=true, chaque session gagne un tableau messages dont les entrées contiennent id, body, direction, timestamp, type, channel et status.
Récupérer un fil de discussion
GET /contacts/{contactId}/chat-sessions/{sessionId}/messages
Une session de chat regroupe les messages d’un contact dans une seule fenêtre de conversation. Ce point de terminaison renvoie le fil complet d’une session unique, du plus ancien au plus récent, ainsi que les métadonnées de la session. Vous pouvez trouver les identifiants de session d’un contact via les points de terminaison des sessions de chat.
cURL
curl "https://api.youraiconnector.com/v1/contacts/contact123/chat-sessions/session456/messages" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/chat-sessions/session456/messages",
{ headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.session, data.messages);
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/contacts/contact123/chat-sessions/session456/messages",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
print(data["session"], data["messages"])
Réponse (200 OK) :
{
"success": true,
"contact_id": "contact123",
"session": {
"id": "session456",
"status": "ChatSessionClosed",
"start_date_time": "2026-06-01T09:55:00.000Z",
"end_date_time": "2026-06-01T10:20:00.000Z",
"tag": "Booking enquiry"
},
"messages": [
{
"id": "aB3dE5fG7hI9jK1lM2nO",
"body": "Hi! Thanks for reaching out.",
"direction": "inbound",
"channel": "whatsapp",
"status": "delivered",
"type": null,
"timestamp": "2026-06-01T09:55:00.000Z",
"media_url": null,
"media_content_type": null,
"bot_reply": false
}
]
}
L’objet session rapporte status (ChatSessionOpened lorsqu’elle est active, ChatSessionClosed une fois terminée), start_date_time, end_date_time, et un tag lisible par l’homme. Le tableau messages utilise les mêmes champs de message que le point de terminaison de liste.
Modifier, supprimer et réagir aux messages
Ces points de terminaison modifient un message après son envoi. Deux d’entre eux interagissent avec le canal du contact ainsi qu’avec votre propre copie. Lisez donc l’introduction de la section avant de les configurer — ce qui est possible dépend entièrement du canal sur lequel se déroule la conversation.
Ce que chaque canal permet
| Action | Canaux pouvant modifier la copie du contact | Délai imparti |
|---|---|---|
| Modifier un message envoyé | Widget de chat, WhatsApp Web (messages texte uniquement), Telegram, LinkedIn | Aucun sur le widget de chat, 15 minutes sur WhatsApp Web, 48 heures sur Telegram, 60 minutes sur LinkedIn |
| Supprimer pour tout le monde | Widget de chat, WhatsApp Web, Telegram, LinkedIn | 60 minutes sur LinkedIn ; les autres n’ont pas de limite publiée |
| Réagir avec un émoji | WhatsApp Web, Telegram | Aucun |
Sur tous les autres canaux — l’API WhatsApp Business, SMS, Instagram, Messenger, e-mail, LINE, canaux personnalisés — une suppression retire toujours le message de votre boîte de réception, mais le contact conserve sa copie, et la modification ou la réaction est totalement impossible.
Modifier un message
POST /contacts/{contactId}/messages/{messageId}/edit
Réécrit un message que vous avez déjà envoyé, sur l’appareil du contact et dans votre copie.
| Champ | Requis | Description |
|---|---|---|
body |
Oui | Le nouveau texte du message. Ne doit pas être vide et ne doit pas dépasser la limite autorisée par le canal pour un seul message (les mêmes limites par canal que pour Envoyer par ID de contact ; 4 096 lorsque le message n’a pas de canal). |
Contrairement à la suppression, cette opération échoue de manière explicite lorsque le canal refuse : vous recevez une 409 et votre copie reste exactement telle que le contact la voit, car afficher une modification qu’il n’a jamais reçue créerait un décalage entre les deux parties. Le champ edit_reason vous indique pourquoi : la fenêtre de modification du canal est fermée, le canal est déconnecté, le message contient une pièce jointe que le canal ne peut pas modifier (media_not_editable : sur WhatsApp Web, seuls les messages texte peuvent être modifiés, pas le texte accompagnant une photo, une vidéo ou un fichier), ou une autre erreur est survenue.
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1/edit" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "body": "Sorry - I meant Thursday at 3pm." }'
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1/edit",
{
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ body: "Sorry - I meant Thursday at 3pm." }),
}
);
const data = await res.json();
console.log(data.edited, data.edit_reason);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1/edit",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={"body": "Sorry - I meant Thursday at 3pm."},
)
data = res.json()
print(data.get("edited"), data.get("edit_reason"))
Réponse (200 OK) :
{
"success": true,
"contact_id": "contact123",
"message_id": "msg_1",
"edited": true,
"edit_reason": "edit_dispatched"
}
Si le canal n’accepte pas la modification, vous obtenez une 409 à la place, et rien n’est modifié :
{
"success": false,
"error": "The message could not be edited",
"edit_reason": "channel_disconnected"
}
Un message déjà supprimé, un canal qui ne permet aucune modification et un message trop ancien pour son canal renvoient tous une 400 — la requête n’atteint jamais le canal.
Supprimer un message
DELETE /contacts/{contactId}/messages/{messageId}
Supprime le message de votre conversation et, lorsque le canal le permet, retire également la copie du contact. Aucun corps de requête.
Ceci répond toujours 200 lorsque le message existait, même si la copie du contact n’a pas pu être retirée — votre copie est supprimée, donc une erreur serait trompeuse. Lisez les trois champs de la réponse pour indiquer à l’utilisateur ce qui s’est réellement passé :
| Champ | Description |
|---|---|
revoke_supported |
Indique si ce canal peut retirer des messages. |
revoked |
Indique si la copie sur l’appareil du contact a été supprimée. |
revoke_reason |
Pourquoi elle n’a pas été supprimée, lorsque revoked est false — par exemple revoke_window_closed ou already_deleted. |
cURL
curl -X DELETE "https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1",
{ method: "DELETE", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.revoked, data.revoke_reason);
Python
import requests
res = requests.delete(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
print(data["revoked"], data["revoke_reason"])
Réponse (200 OK) :
{
"success": true,
"contact_id": "contact123",
"message_id": "msg_1",
"revoke_supported": true,
"revoked": true,
"revoke_reason": "revoke_dispatched"
}
Les messages supprimés ne sont pas retirés de l’historique de la conversation. Ils restent dans
GET /contacts/{contactId}/messagesavecis_deleted: trueainsi qu’unbodyet unmedia_urlvides.
Supprimer plusieurs messages à la fois
POST /contacts/{contactId}/messages/bulk-delete
Efface un lot de messages de votre côté uniquement. Le corps et les pièces jointes sont vidés, mais rien n’est rétracté sur l’appareil du contact — pour également retirer un message, supprimez-le un par un avec le point de terminaison pour message unique ci-dessus.
| Champ | Requis | Description |
|---|---|---|
message_ids |
Oui | Un tableau non vide d’identifiants de message, jusqu’à 500 par requête. messageIds est accepté comme alias. |
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/messages/bulk-delete" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "message_ids": ["msg_1", "msg_2"] }'
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/bulk-delete",
{
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ message_ids: ["msg_1", "msg_2"] }),
}
);
console.log((await res.json()).deleted);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/bulk-delete",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={"message_ids": ["msg_1", "msg_2"]},
)
print(res.json()["deleted"])
Réponse (200 OK) :
{
"success": true,
"contact_id": "contact123",
"deleted": 2
}
Réagir à un message
POST /contacts/{contactId}/messages/{messageId}/react
Ajoute votre propre réaction emoji sur un message, ou la retire en envoyant une chaîne vide. Les réactions du contact ne sont jamais modifiées.
| Champ | Requis | Description |
|---|---|---|
emoji |
Oui | L’emoji avec lequel réagir, ou "" pour supprimer votre réaction. Doit être une chaîne unique sans espaces, de 16 caractères maximum. |
Tout comme pour la modification, cela échoue plutôt que d’afficher une réaction que le contact n’a jamais reçue, et l’échec vous indique si une nouvelle tentative en vaut la peine :
422— il ne pourra jamais être délivré dans cette conversation : le canal ne prend pas en charge les réactions, le message n’a pas d’identifiant côté canal, ou l’emoji est en dehors de l’ensemble autorisé par ce canal.409— le canal était momentanément inaccessible. Une nouvelle tentative peut fonctionner.
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1/react" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "emoji": "👍" }'
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1/react",
{
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ emoji: "👍" }),
}
);
const data = await res.json();
console.log(data.reactions);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1/react",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={"emoji": "👍"},
)
print(res.json()["reactions"])
Réponse (200 OK) :
{
"success": true,
"contact_id": "contact123",
"message_id": "msg_1",
"reaction_supported": true,
"reaction_reason": "reaction_dispatched",
"reactions": [
{
"emoji": "👍",
"from_phone_number": "+31612345678",
"from_me": true,
"reacted_at": "2026-06-01T10:05:00.000Z"
}
]
}
Le tableau reactions est l’ensemble complet des réactions présentes sur le message, les vôtres et celles du contact. Sur un 409 ou un 422, il est renvoyé inchangé, de sorte qu’un client effectuant le rendu directement à partir de celui-ci n’affiche jamais une réaction qui n’a pas été délivrée.
Évaluer ou marquer un message
PATCH /contacts/{contactId}/messages/{messageId}
Évalue un message avec un pouce levé ou baissé et/ou le marque comme important. Il s’agit d’une gestion interne de votre côté uniquement — rien n’est envoyé au contact.
| Champ | Requis | Description |
|---|---|---|
score |
Non | 1 pouce levé, -1 pouce baissé, 0 efface l’évaluation. |
is_important |
Non | true ajoute une étoile au message, false retire l’étoile. Doit être un booléen réel, pas la chaîne "true". |
Envoyez au moins l’un des deux, sinon vous recevrez une 400. Seul ce que vous envoyez est écrit, donc ajouter une étoile à un message n’efface jamais son évaluation et vice versa — et la réponse ne renvoie que les champs que vous avez envoyés.
cURL
curl -X PATCH "https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "score": 1, "is_important": true }'
JavaScript
await fetch("https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1", {
method: "PATCH",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ score: 1, is_important: true }),
});
Python
import requests
requests.patch(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"score": 1, "is_important": True},
)
Réponse (200 OK) :
{
"success": true,
"contact_id": "contact123",
"message_id": "msg_1",
"score": 1,
"is_important": true
}
Marquer les messages comme lus
Vous pouvez supprimer l’état non lu soit pour des messages spécifiques, soit pour l’ensemble de la conversation.
Marquer des messages spécifiques comme lus
POST /contacts/{contactId}/messages/mark-read
Transmettez les identifiants des messages à marquer comme lus.
| Champ | Requis | Description |
|---|---|---|
message_ids |
Oui | Un tableau non vide d’identifiants de message (jusqu’à 500 par requête). |
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/messages/mark-read" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message_ids": ["aB3dE5fG7hI9jK1lM2nO", "cD4eF6gH8iJ0kL2mN3oP"]
}'
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/mark-read",
{
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
message_ids: ["aB3dE5fG7hI9jK1lM2nO", "cD4eF6gH8iJ0kL2mN3oP"],
}),
}
);
const data = await res.json();
console.log(data.marked_read);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/mark-read",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={"message_ids": ["aB3dE5fG7hI9jK1lM2nO", "cD4eF6gH8iJ0kL2mN3oP"]},
)
print(res.json()["marked_read"])
Réponse (200 OK) :
{
"success": true,
"contact_id": "contact123",
"marked_read": 2
}
Marquer l’intégralité du chat comme lu
POST /contacts/{contactId}/mark-read
Supprime le badge de non-lu pour toute la conversation du contact dans la boîte de réception. Aucun corps de requête n’est requis.
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/mark-read" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/mark-read",
{ method: "POST", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.success);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/contact123/mark-read",
headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["success"])
Réponse (200 OK) :
{
"success": true,
"contact_id": "contact123"
}
Marquer toute la conversation comme non lue
POST /contacts/{contactId}/mark-unread
Remet le badge de non lu sur la conversation — pratique lorsqu’un membre de votre équipe a ouvert une discussion mais la transmet à quelqu’un d’autre. Aucun corps de requête n’est requis.
Il s’agit d’un indicateur propre à la boîte de réception : il ne modifie pas la date de dernière lecture de la conversation, donc aucun accusé de lecture n’est envoyé au contact sur les canaux qui les prennent en charge.
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/mark-unread" \
-H "X-API-Key: YOUR_API_KEY"
Réponse (200 OK) :
{
"success": true,
"contact_id": "contact123"
}
Exporter une conversation
Les exportations vous fournissent une conversation entière sous forme de transcription lisible, plutôt que de parcourir les messages page par page. Chaque point de terminaison d’exportation accepte un filter de all (par défaut), text, media ou tool_use, correspondant au filtre de la liste des messages.
Exporter la discussion d’un contact
GET /chat-exports/{contactId}
| Paramètre de requête | Requis | Description |
|---|---|---|
format |
Non | txt (par défaut) renvoie un lien de téléchargement vers une transcription en texte brut. json renvoie les messages sous forme de données structurées dans la réponse. |
filter |
Non | all (par défaut), text, media ou tool_use. |
cURL
curl "https://api.youraiconnector.com/v1/chat-exports/contact123?format=json" \
-H "X-API-Key: YOUR_API_KEY"
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/chat-exports/contact123",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"format": "json"},
)
print(res.json()["data"]["messages"])
Réponse avec format=json (200 OK) :
{
"success": true,
"data": {
"contact": {
"id": "contact123",
"name": "Jane Doe",
"phone": "+31612345678",
"email": "jane@example.com"
},
"messages": [
{
"body": "Hi! I have a question about my order.",
"direction": "inbound",
"timestamp": "2026-06-01T09:55:00.000Z",
"type": "text",
"media_url": null,
"media_content_type": null,
"name": null,
"args": null
}
]
}
}
Avec format=txt (la valeur par défaut), data est plutôt un lien de téléchargement vers le fichier de transcription généré :
{
"success": true,
"data": "https://storage.googleapis.com/.../chat-export-contact123-....txt"
}
Le lien de téléchargement est éphémère. Récupérez le fichier dès que vous obtenez le lien plutôt que de le stocker — demandez une nouvelle exportation lorsque vous avez à nouveau besoin de la transcription.
Exporter toutes les conversations récentes
GET /chat-exports/recent
Exporte les conversations de tous les contacts ayant été actifs au cours des X dernières heures, en un seul appel.
| Paramètre de requête | Requis | Description |
|---|---|---|
hours |
Oui | Nombre d’heures d’activité à prendre en compte. Doit être un nombre entier positif. |
format |
Non | json (par défaut) renvoie une entrée par contact. txt renvoie un fichier texte unique téléchargeable contenant toutes les conversations. |
limit |
Non | Nombre maximum de contacts à exporter. Par défaut 50, maximum 100. |
filter |
Non | all (par défaut), text, media ou tool_use. |
cURL
curl "https://api.youraiconnector.com/v1/chat-exports/recent?hours=24&limit=25" \
-H "X-API-Key: YOUR_API_KEY"
Réponse (200 OK) :
{
"success": true,
"data": {
"hours_ago": 24,
"total_contacts": 2,
"exports": [
{
"contactId": "contact123",
"contactName": "Jane Doe",
"phoneNumber": "+31612345678",
"email": "jane@example.com",
"messageCount": 12,
"chatExport": "Acme Export - Jane Doe\nPhone: +31612345678\n..."
}
]
}
}
Avec format=txt, la réponse est le fichier texte lui-même, envoyé en tant que téléchargement plutôt qu’au format JSON.
Cet appel unique extrait l’historique complet de chaque contact correspondant, veillez donc à ce que
hoursetlimitrestent raisonnables sur les comptes très actifs.
Envoyer une transcription par e-mail au contact
POST /chat-exports/{contactId}/email
Envoie au contact sa propre transcription de conversation par e-mail — le flux « m’envoyer cette discussion par e-mail », piloté depuis votre propre système.
| Champ | Requis | Description |
|---|---|---|
recipient_email |
Non | Où l’envoyer. Par défaut, l’adresse e-mail enregistrée du contact. |
via |
Non | auto (par défaut) choisit le meilleur itinéraire, transactional l’envoie en tant qu’e-mail système, email_channel l’envoie depuis votre canal e-mail connecté. |
note |
Non | Une courte ligne de votre part affichée au-dessus de la transcription. Jusqu’à 1000 caractères. |
cURL
curl -X POST "https://api.youraiconnector.com/v1/chat-exports/contact123/email" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "note": "Here is a copy of our chat, as promised." }'
Réponse (200 OK) :
{
"success": true,
"data": {
"via": "transactional",
"recipientEmail": "jane@example.com",
"messageCount": 42,
"omittedCount": 0
}
}
omittedCount vous indique combien des messages les plus anciens ont été omis pour conserver une longueur raisonnable à l’e-mail. Un 200 signifie que la transcription a été générée et mise en file d’attente pour l’envoi, et non qu’elle est déjà arrivée dans la boîte de réception.
Mettre en pause ou reprendre l’IA pour un contact
PUT /contacts/{contactId}
Définissez is_bot_active sur false pour empêcher l’IA de répondre à un contact, et remettez-le sur true pour lui rendre la conversation. C’est l’interrupteur de prise en main que vous souhaitez utiliser lorsqu’un humain intervient dans une conversation : les messages sortants que vous envoyez via l’API sont toujours délivrés pendant que le bot est en pause.
cURL
curl -X PUT "https://api.youraiconnector.com/v1/contacts/contact123" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "is_bot_active": false }'
JavaScript
await fetch("https://api.youraiconnector.com/v1/contacts/contact123", {
method: "PUT",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ is_bot_active: false }),
});
Python
import requests
requests.put(
"https://api.youraiconnector.com/v1/contacts/contact123",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"is_bot_active": False},
)
Réponse
{
"success": true,
"contact_id": "contact123"
}
Mise en pause lors d’une réponse
Si un humain prend le relais en envoyant une réponse, vous pouvez mettre le bot en pause dans la même requête au lieu d’effectuer un second appel. POST /contacts/{contactId}/send-message accepte ces indicateurs optionnels :
| Champ | Description |
|---|---|
pauseBot |
true met l’IA en pause pour ce contact lors de l’envoi du message. |
clearIncompleteReply |
true ignore une réponse du bot en cours de rédaction afin qu’elle ne reprenne pas après. |
human_reply |
true marque le message comme étant une réponse d’un membre de l’équipe et annule une réponse que l’IA avait mise en file d’attente. La mise en pause nécessite toujours pauseBot. |
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/send-message" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"body": "Hi, Sarah here - taking over from the assistant.",
"pauseBot": true,
"clearIncompleteReply": true,
"human_reply": true
}'
La réponse inclut "botPaused": true lorsque la pause a été appliquée.
Marquer un contact comme privé avec
POST /contacts/bulk-flagmet également le bot en pause pour lui. Voir Contacts pour la liste complète des champs.
Créer votre propre boîte de réception
Tout ce dont une boîte de réception a besoin se trouve sur cette page et dans Contacts :
| Ce dont vous avez besoin | Point de terminaison |
|---|---|
| Lister les conversations | GET /contacts |
| Lire une conversation | GET /contacts/{contactId}/messages |
| Lister les sessions de chat d’un contact | GET /chat-sessions/{contactId} |
| Voir ce qui est arrivé récemment | GET /chat-sessions/recent |
| Lire une session de chat | GET /contacts/{contactId}/chat-sessions/{sessionId}/messages |
| Envoyer une réponse manuelle | POST /contacts/{contactId}/send-message |
| Corriger une réponse que vous venez d’envoyer | POST /contacts/{contactId}/messages/{messageId}/edit |
| Supprimer un message | DELETE /contacts/{contactId}/messages/{messageId} |
| Effacer plusieurs messages | POST /contacts/{contactId}/messages/bulk-delete |
| Réagir avec un emoji | POST /contacts/{contactId}/messages/{messageId}/react |
| Noter ou marquer un message | PATCH /contacts/{contactId}/messages/{messageId} |
| Marquer comme lu | POST /contacts/{contactId}/mark-read |
| Rendre une discussion à l’équipe | POST /contacts/{contactId}/mark-unread |
| Exporter une transcription | GET /chat-exports/{contactId} |
| Suspendre ou reprendre l’IA | PUT /contacts/{contactId} avec is_bot_active |
Pour des mises à jour en temps réel, abonnez-vous aux événements New Message, Replies, Human Alerted et Chat Concluded avec les Webhooks plutôt que d’interroger cette API de manière répétée.
Erreurs de l’API Messages
Les points de terminaison de message renvoient l’enveloppe d’erreur standard :
{
"success": false,
"error": "Contact not found"
}
| Statut | Quand cela se produit sur un point de terminaison de message |
|---|---|
400 |
Un champ requis est manquant ou un paramètre est invalide (mauvais limit, hours, filter, direction, status, un tableau message_ids vide ou de plus de 500 éléments, un cursor invalide, une modification body vide ou trop longue, un score en dehors de -1/0/1, ou un emoji avec des espaces ou plus de 16 caractères). Également renvoyé lorsqu’un message ne peut pas être modifié du tout — il a été supprimé, son canal ne permet pas la modification, ou il est en dehors de la fenêtre de modification de ce canal. |
404 |
Le contact, la session de chat ou l’un des identifiants de message fournis n’a pas été trouvé. |
409 |
Le canal n’accepte pas la modification pour le moment. Rien n’a été écrit : lors d’une modification, edit_reason explique pourquoi ; lors d’une réaction, le canal était momentanément inaccessible et une nouvelle tentative peut fonctionner. |
422 |
Le contact ne peut pas recevoir de messages sortants (ne pas déranger, privé ou canal non pris en charge), ou une réaction ne peut jamais être délivrée sur cette conversation (reaction_reason indique lequel). |
Les codes partagés que chaque point de terminaison peut renvoyer — 401, 403 (votre forfait n’inclut pas l’accès à l’API), 429 (limite de débit) et 500 — sont répertoriés avec des conseils de nouvelle tentative dans Erreurs et pagination.
Étapes suivantes
- Webhooks — recevez des mises à jour sur le statut de livraison au lieu d’interroger le serveur.
- Contacts — créez et recherchez les contacts auxquels vous envoyez des messages.
- Rendez-vous — réservez et gérez les rendez-vous de vos contacts.