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.
Envoyer par ID de contact
POST /contacts/{contactId}/send-message
| Champ | Requis | Description |
|---|---|---|
body |
Oui | Le texte du message à envoyer. |
mediaUrl |
Non | URL d’un fichier média (image, document, etc.) à joindre. |
mediaContentType |
Non | Type MIME du média joint, par ex. image/jpeg. |
pauseBot |
Non | true met l’IA en pause pour ce contact lors de l’envoi du message — pour une intervention humaine. Voir Mettre en pause ou reprendre l’IA. |
clearIncompleteReply |
Non | true annule une réponse du bot en cours de rédaction afin qu’elle ne reprenne pas après votre message. |
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. |
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 utilisé pour l’envoi. 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.
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. |
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 ISO 8601 de création du message. |
media_url |
URL d’un fichier multimédia joint, le cas échéant. |
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 marquer un message. |
is_important |
true lorsque le message a été marqué d’une étoile. |
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 s’il n’y en a pas. Chaque entrée contient emoji, from_phone_number, from_me (true lorsque la réaction est la vôtre) et reacted_at. |
Lister les sessions de discussion
Une session de discussion est une fenêtre de conversation avec un contact : elle s’ouvre lorsqu’il commence à parler et se ferme lorsque la conversation est terminée. Les sessions vous permettent de diviser un long historique en conversations lisibles plutôt qu’en 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 |
|---|---|---|
| Modifier un message envoyé | Widget de chat, WhatsApp Web, Telegram, LinkedIn | Aucun pour 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 emoji | 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 peut contenir au maximum 4096 caractères. |
Contrairement à la suppression, cette opération échoue bruyamment lorsque le canal refuse : vous obtenez une 409 et votre copie reste exactement telle que le contact l’a, 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é 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 deux options facultatives :
| Champ | Description |
|---|---|
pauseBot |
true met l’IA en pause pour ce contact lors de l’envoi du message. |
clearIncompleteReply |
true annule une réponse du bot en cours de rédaction afin qu’elle ne reprenne pas par la suite. |
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
}'
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.