Your AI Connector Docs

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/send et 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 erreur 404.

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 filter et direction sont appliqués à chaque page après sa lecture ; une page filtrée peut donc contenir moins d’éléments que limit. Le next_cursor continue de progresser dans la conversation complète, donc continuez la pagination jusqu’à ce que next_cursor soit null.

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’appelle id. 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}/messages avec is_deleted: true ainsi qu’un body et un media_url vides.

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 hours et limit restent 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-flag met é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.