Conversations et messages
Démarrez des chats, envoyez des messages de suivi, recevez les réponses en streaming par WebSocket, comparez des modèles, approuvez les appels d'outils MCP et partagez des conversations avec l'API REST.
Une conversation est un fil de chat, exactement ce que votre équipe voit sous Chat History dans l’application. Vous la démarrez avec un message, le modèle répond, puis vous poursuivez avec des messages de suivi. Chaque requête décrite ici s’exécute au nom de l’utilisateur propriétaire de la clé API, avec les mêmes accès, quotas et règles d’espace de travail que cet utilisateur dans le navigateur.
Tous les chemins sont relatifs à https://api.stickyprompts.com/api/v1. Les corps de requête sont en JSON. Les fichiers sont d’abord envoyés via les endpoints de fichiers, puis référencés par leur ID.
Fonctionnement du chat
- Démarrez avec
POST /conversation(attend la réponse complète) ouPOST /conversation/stream(rend la main aussitôt ; la réponse arrive par le WebSocket). Les deux créent la conversation et envoient le premier message en un seul appel. - Poursuivez avec
POST /conversation/:idouPOST /conversation/:id/stream. - Changez de modèle, de style ou de niveau de raisonnement pour les tours suivants avec
PATCH /conversation/:id/model. Les corps des messages de suivi n’acceptent pas de modèle : la conversation mémorise ses réglages « prochain message ». - Lisez l’historique avec
GET /conversation/:id(paginé, du plus récent au plus ancien) et listez les conversations avecGET /conversation. - Suivez la progression en direct avec le WebSocket
GET /conversation/:id/ws, ou interrogez régulièrementGET /conversation/:idet lisez lestatusdu message de l’IA.
Identifiants. La plupart des endpoints acceptent comme :id soit l’ID numérique de la conversation, soit son slug de 8 caractères. Les endpoints de partage, la suppression, l’approbation ainsi que les flux WebSocket et SSE n’acceptent que l’ID numérique ; chaque cas est signalé plus bas.
L’objet Message
Renvoyé par les endpoints d’envoi sans streaming, à l’intérieur de GET /conversation/:id, et comme data des événements WebSocket message.
{
"ID": 90412,
"CreatedAt": "2026-09-28T09:14:03.512Z",
"UpdatedAt": "2026-09-28T09:14:09.871Z",
"DeletedAt": null,
"conversation_context_id": 5120,
"ai_model_id": 12,
"ai_model": { "ID": 12, "name": "Example Model", "stream_support": true, "...": "..." },
"agent_id": null,
"is_auto_model": false,
"text": "Here are three subject lines for the Northwind Q4 newsletter: ...",
"raw_text": "Here are three subject lines for the Northwind Q4 newsletter: ...",
"parts": [
{ "id": "p1", "type": "text", "static": true, "text_part": { "text": "Here are three ...", "raw_text": "Here are three ..." } }
],
"thinking": null,
"isUser": false,
"error_text": null,
"error_id": null,
"error_code": null,
"mcp_approval_requests": null,
"ai_style": "prompty",
"status": "finished",
"citations": null,
"response_duration_ms": 6210,
"type": "normal",
"attachments": []
}
| Champ | Type | Signification |
|---|---|---|
conversation_context_id | uint ou null | La conversation à laquelle appartient ce message. |
ai_model_id, ai_model | uint, object | Le modèle qui a produit ce message (IA) ou qui a été sélectionné pour lui (utilisateur). |
agent_id, agent | uint, object | L’agent qui a répondu, le cas échéant. |
is_auto_model | bool | true lorsque le routage automatique a choisi le modèle. |
prompt_id | uint ou null | Prompt enregistré utilisé pour ce message utilisateur. |
text | string | Texte du message. Dans les messages de l’IA, les marqueurs de citation sont déjà rendus. |
raw_text | string | Le texte de l’IA brut, non traité (chemins de lecture et de streaming uniquement). |
parts | array | Blocs structurés. type vaut text, thinking, web_search, web_fetch, code_execution, image_generation ou mcp_call, avec l’objet *_part correspondant. static vaut true lorsqu’il n’y a rien à déplier. |
thinking | string ou null | Texte de raisonnement des modèles de raisonnement. |
isUser | bool | true pour les messages utilisateur, false pour ceux de l’IA. |
status | string | thinking, generating ou finished. |
error_text, error_id, error_code | string ou null | Renseignés en cas d’échec de la génération. error_id est une référence de support de 10 caractères ; error_code est un code machine propre à certaines catégories d’échec, comme les blocages liés aux données sensibles et les erreurs MCP. |
mcp_approval_requests | array | Approbations d’outils MCP en attente ou déjà décidées. Voir Approbation des outils MCP. |
tools | array | Outils activés pour ce tour. |
citations | array | Citations web et de bases de connaissances : url, file_path, title, info (kb_id, file_id, plages de pages et de lignes), citation_index, etc. |
knowledge_base_ids, world_knowledge | uint[], bool | Bases de connaissances interrogées pour ce tour, et possibilité ou non pour le modèle d’aller au-delà. |
response_duration_ms | int ou null | Durée de génération. |
type | string | normal ou sub_conversation (conteneur d’une comparaison de modèles). |
attachments | array | Fichiers et transcriptions joints, chacun avec une première clé "type": "file" ou "type": "transcription". Toujours un tableau. |
Statut. thinking signifie que la ligne du message de l’IA existe mais que rien n’est encore généré ; generating, que la sortie partielle arrive en streaming ; finished, que la génération est terminée. Un message de l’IA en échec est lui aussi finished, avec error_text et error_id renseignés : vérifiez donc ces champs, pas seulement status. Les messages utilisateur sont toujours finished.
Crédits. Chaque champ credits_used est un nombre décimal sérialisé sous forme de chaîne JSON, par exemple "0.4213".
Envoyer des messages
Corps de la requête
POST /conversation et POST /conversation/stream acceptent tous les champs ci-dessous. Les endpoints de suivi n’acceptent que les champs marqués « suivi » ; les autres sont ignorés sans avertissement. Côté validation, aucun champ n’est strictement obligatoire, mais envoyez toujours un message et un modèle.
-
messagestring facultatif - Le message de l’utilisateur. Mentionnez
@<agent-tag>pour confier ce tour à l’un de vos agents. Démarrage et suivi. -
attachmentsarray facultatif - Éléments
{ "id": uint, "type": "file" | "transcription", "temp": bool }. Fichiers envoyés ou transcriptions terminées.temp: trueutilise la pièce jointe pour ce tour seulement, sans l’enregistrer sur le message. Démarrage et suivi. -
knowledge_base_idsuint[] facultatif - Bases de connaissances dont tirer le contexte pour ce tour. Démarrage et suivi.
-
knowledge_base_limit_node_idsuint[] facultatif - Limite la recherche à ces dossiers ou fichiers de base de connaissances. Démarrage et suivi.
-
world_knowledgebool facultatif par défautfalse false: réponse fondée uniquement sur la base de connaissances.true: la base de connaissances reste prioritaire, mais le modèle peut aussi recourir à la recherche web et à ses propres connaissances. Démarrage et suivi.-
flash_modebool facultatif - Demande le niveau de service prioritaire du fournisseur. N’a d’effet que sur les modèles qui le prennent en charge. Démarrage et suivi.
-
toolsarray facultatif - Éléments
{ "name", "use", "mcp_tool_id"? }. Voir Outils. Démarrage et suivi. -
ai_model_iduint facultatif - Modèle à utiliser, issu de
GET /ai_model. Ignoré siauto_model_typeest défini. Démarrage uniquement. -
auto_model_typestring facultatif best,balancedoucheapest. Le routage automatique choisit le meilleur modèle pour chaque message et prime surai_model_id. Démarrage uniquement.-
ai_stylestring facultatif par défautprompty - Style de réponse : la valeur
toned’un style d’IA. Démarrage uniquement. -
reasoning_effortstring facultatif - Niveau de raisonnement des modèles de raisonnement. Une valeur non prise en charge est remplacée par la valeur par défaut du modèle ; pour les modèles sans raisonnement, la valeur enregistrée est null. Démarrage uniquement.
-
agent_iduint facultatif - Démarre un chat d’agent : le modèle, le prompt système, les outils, les serveurs MCP, les bases de connaissances et les fichiers de l’agent servent à chaque tour. L’agent doit vous appartenir. Démarrage uniquement.
-
invited_agent_idsuint[] facultatif - Ceux de vos agents que l’on peut mentionner (
@mentioned) dans cette conversation. Ignoré lorsqueagent_idest défini. Démarrage uniquement. -
team_iduint facultatif - Crée une conversation d’équipe (l’équipe obtient l’accès
chat_contribute). Voir Quand l’IA répond. Démarrage uniquement. -
X-Project-IDinteger dans header facultatif - Démarrage uniquement. Classe la conversation dans ce projet. Si le corps ne précise aucun modèle, c’est le modèle par défaut du projet qui est utilisé. À chaque tour, les fichiers du projet sont ajoutés au contexte. Le champ
project_idexiste dans le corps mais n’est pas lu : utilisez ce header.
Choix du modèle. auto_model_type l’emporte, puis ai_model_id, puis le modèle par défaut du projet (avec X-Project-ID). Si aucun ne s’applique, la conversation est tout de même créée, mais l’envoi échoue avec 503 {"error":"no AI model is selected, try reselecting model"} : envoyez donc toujours un modèle ou un type automatique au démarrage. Il n’existe pas d’ID de modèle littéral "auto". Les chats d’agent et les mentions @agent utilisent le modèle de l’agent (style prompty, sans niveau de raisonnement). Le modèle doit être autorisé par les règles d’accès aux modèles et de résidence des données de votre espace de travail, faute de quoi l’envoi échoue avec 503.
Outils
Chaque entrée a la forme { "name": ..., "use": true | false }. Noms possibles : web_search, image_generation, video_generation, speech_generation, music_generation, remote_mcp.
- Un outil n’atteint le modèle que si celui-ci le déclare dans ses capacités
tools. Sinon, il est ignoré sans avertissement. remote_mcpexige aussi"mcp_tool_id": <id>, l’ID de l’un de vos serveurs MCP distants configurés. Ajoutez une entrée par serveur.- Sélection automatique des outils. Sur les modèles qui prennent en charge les outils, un petit classifieur peut activer
web_searchetimage_generation(ainsi que l’exécution de code) en fonction du message, même sans demande de votre part. Envoyer une entrée pour un outil, même{"name":"web_search","use":false}, empêche le classifieur de l’ajouter. L’exécution de code relève uniquement du classifieur.
POST /conversation
/api/v1/conversation Crée une conversation, envoie le premier message et attend la réponse complète de l’IA, appels d’outils compris. La réponse est le Message de l’IA terminé ; l’ID de la nouvelle conversation figure dans son conversation_context_id. La conversation reçoit un nom automatique après le premier échange. Accepte le corps de requête ci-dessus, ainsi que le header facultatif X-Project-ID.
curl -X POST https://api.stickyprompts.com/api/v1/conversation \
-H "Authorization: Bearer $STICKY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message": "Draft three subject lines for the Northwind Q4 newsletter.",
"ai_model_id": 12,
"ai_style": "prompty",
"tools": [{ "name": "web_search", "use": false }]
}'import os, requests
r = requests.post(
"https://api.stickyprompts.com/api/v1/conversation",
headers={"Authorization": f"Bearer {os.environ['STICKY_API_KEY']}"},
json={
"message": "Draft three subject lines for the Northwind Q4 newsletter.",
"ai_model_id": 12,
"ai_style": "prompty",
"tools": [{"name": "web_search", "use": False}],
},
timeout=300,
)
r.raise_for_status()
reply = r.json()
if reply.get("error_id"):
print("Failed:", reply["error_text"], reply["error_id"])
else:
print(reply["conversation_context_id"], reply["text"])const res = await fetch("https://api.stickyprompts.com/api/v1/conversation", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.STICKY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
message: "Draft three subject lines for the Northwind Q4 newsletter.",
ai_model_id: 12,
ai_style: "prompty",
tools: [{ name: "web_search", use: false }],
}),
});
const reply = await res.json();
console.log(reply.conversation_context_id, reply.error_id ?? reply.text);Réponse. 200 avec le Message de l’IA (voir l’objet Message). Lorsque l’IA n’est pas censée répondre (conversation d’équipe à plusieurs membres, sans mention @ai ni mention d’agent), le corps est à la place 200 {"conversation_context_id": 5120}.
Erreurs
| Statut | Corps | Cas |
|---|---|---|
400 | {"error": "..."} | JSON mal formé. |
400 | {"error": "...", "error_code": "..."} | Blocage par les règles de votre espace de travail relatives aux données sensibles, ou erreur d’un serveur MCP. Lorsque l’IA ne répond pas, un blocage lié aux données sensibles utilise la clé code au lieu de error_code. |
400 | {"error": "Knowledge base not found"} | Base de connaissances inconnue. |
429 | {"error": "Quota exceeded", "reason": "..."} | Vérifié avant toute création. reason vaut credit_count, user_count, subscription, trial_expired ou unknown. |
503 | {"error": "could not create conversation"} | Par exemple un agent_id qui ne vous appartient pas ou un team_id inconnu (l’échec de la recherche d’équipe peut aussi se traduire par un 500). |
503 | {"error": "<message>"} | Tout autre échec : aucun modèle sélectionné, modèle soumis à restriction, erreur du fournisseur. |
Si le fournisseur échoue en cours de génération, le message de l’IA est tout de même enregistré avec error_text et error_id, et POST /conversation/:id/retry permet de le relancer.
POST /conversation/stream
/api/v1/conversation/stream Mêmes headers et même corps que POST /conversation, mais l’appel rend la main dès que le message utilisateur est enregistré. La génération se poursuit en arrière-plan et la réponse arrive par le WebSocket ou par interrogation périodique.
{ "conversation_context_id": 5120 }
Les erreurs détectées avant l’enregistrement du message utilisateur (quota 429, agent non valide, aucun modèle sélectionné, modèle soumis à restriction, blocage lié aux données sensibles) sont toujours renvoyées de façon synchrone, sous la même forme que ci-dessus. Les erreurs survenant après le 200 (choix du modèle ou des outils, récupération de la base de connaissances, erreur du fournisseur) ne sont signalées que par un événement WebSocket error_message et enregistrées sur un message de l’IA avec error_text et error_id.
Récupérer la réponse
- WebSocket (recommandé). Connectez-vous à
GET /conversation/{conversation_context_id}/ws. Les événements émis avant votre connexion sont mis en mémoire tampon et rejoués au premier client : en vous connectant juste après le200, vous ne perdez rien. - Interrogation périodique (polling). Appelez
GET /conversation/:id?page=1&size=2et lisez le message de l’IA le plus récent (isUser: false, en tête de liste puisque l’ordre va du plus récent au plus ancien). Le message de l’IA est créé avecstatus: "thinking"puis enregistré à chaque fragment : vous voyez doncgeneratingavec untextqui s’allonge, puisfinished. Arrêtez-vous àfinishedet vérifiezerror_id. Juste après le200, le message de l’IA n’existe pas forcément encore ; si le message le plus récent est toujours le vôtre, la génération n’a pas commencé.
Le streaming n’est en temps réel que pour les modèles avec stream_support: true. Pour les autres, la réponse apparaît d’un seul bloc une fois terminée.
POST /conversation/:id
/api/v1/conversation/:id Envoie un message de suivi et attend la réponse de l’IA. Le modèle, le style et le niveau de raisonnement proviennent des réglages next_message_* de la conversation ; modifiez-les d’abord avec PATCH /conversation/:id/model.
-
idstring dans path obligatoire - ID ou slug de la conversation.
-
messagestring facultatif - Le texte du message de suivi.
-
attachmentsarray facultatif - Comme dans le corps de requête.
-
knowledge_base_idsuint[] facultatif - Bases de connaissances pour ce tour.
-
knowledge_base_limit_node_idsuint[] facultatif - Limite la recherche à ces nœuds.
-
world_knowledgebool facultatif - Autorise des connaissances au-delà de la base de connaissances.
-
flash_modebool facultatif - Niveau de service prioritaire, lorsqu’il est pris en charge.
-
toolsarray facultatif - Outils pour ce tour.
curl -X POST https://api.stickyprompts.com/api/v1/conversation/5120 \
-H "Authorization: Bearer $STICKY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "message": "Make the second one shorter." }'
Réponse. Identique à POST /conversation : 200 avec le Message de l’IA, ou 200 {"conversation_context_id": ...} lorsque l’IA ne répond pas. Si la conversation comporte une comparaison de modèles active, le message part vers chaque fil en parallèle et la réponse est un tableau JSON de Messages de l’IA, un par fil.
Erreurs. Comme pour POST /conversation, plus 404 {"error":"Conversation not found"}. Seuls le propriétaire et les utilisateurs ou équipes disposant de chat_contribute peuvent envoyer des messages ; les autres reçoivent 503 {"error":"you are not allowed to send messages in this conversation"}.
POST /conversation/:id/stream
/api/v1/conversation/:id/stream Identique à POST /conversation/:id, mais renvoie immédiatement 200 {"conversation_context_id": <id>}. Suivez la progression par le WebSocket ou par interrogation périodique, comme pour POST /conversation/stream. En cas de comparaison de modèles active, chaque fil est diffusé sur le WebSocket de la conversation parente.
-
idstring dans path obligatoire - ID ou slug de la conversation.
Quand l’IA répond
L’IA répond à un message dès que l’une de ces conditions est remplie :
- un seul utilisateur dispose d’un accès en contribution à la conversation (le cas normal, y compris pour toute conversation créée avec une clé API sans
team_id) ; - le texte contient
@ai(sensible à la casse) ; - il s’agit d’un chat d’agent ;
- le texte mentionne (
@mentions) le tag d’un agent invité dans la conversation.
Sinon, le message est enregistré comme simple message utilisateur, visible des autres participants, et l’endpoint renvoie 200 {"conversation_context_id": <id>} sans appeler de modèle, même sur les endpoints sans streaming.
Les agents dans une conversation
- Un
agent_idfourni à la création fait de la conversation un chat d’agent. Son modèle ne peut plus être modifié ensuite. - Dans une conversation à un seul utilisateur,
@tagconfie ce tour à votre propre agent portant ce tag, ou à un agent partagé avec vous (vos propres agents l’emportent en cas de tag identique). Dans une conversation à plusieurs utilisateurs, seuls les agents invités avecinvited_agent_idsouPOST /conversation/:id/agentspeuvent être mentionnés. - L’agent qui répond est enregistré sur le message de l’IA (
agent_id,agent).
Streaming
GET /conversation/:id/ws
/api/v1/conversation/:id/ws Un WebSocket qui transmet chaque mise à jour de la conversation. Connectez-vous à wss://api.stickyprompts.com/api/v1/conversation/5120/ws et envoyez le header Authorization: Bearer STICKY-API-... avec la requête d’upgrade. Les objets WebSocket des navigateurs ne permettent pas de définir des headers : cette connexion est donc réservée aux clients côté serveur. Le serveur ignore tout ce que vous envoyez ; il ne lit le flux que pour en détecter la fermeture.
-
idinteger dans path obligatoire - L’ID numérique de la conversation. Avec un slug, vous vous connectez à un autre flux, vide.
Chaque trame est une trame texte JSON {"type": <string>, "data": <payload>} :
type | data | Cas |
|---|---|---|
message | Message (instantané complet) | Un nouveau message utilisateur d’un autre participant, et chaque mise à jour d’un message de l’IA pendant la génération. text, parts et thinking contiennent tout le contenu accumulé jusque-là, et non un delta : remplacez votre copie en vous fondant sur data.ID. status passe par thinking, generating, puis finished. |
ai_message_end | aucune (clé absente) | Génération terminée, avec ou sans succès. Fin du tour. |
error_message | Message avec error_text, error_id, error_code facultatif, status: "finished" | La génération ou sa préparation a échoué. Considérez-le comme final : un ai_message_end suit généralement les échecs de préparation, mais ce n’est pas garanti après une erreur du fournisseur en cours de génération. |
ai_model_change | { "ai_model_id", "ai_style", "auto_model_type", "reasoning_effort" } | Quelqu’un a appelé PATCH /conversation/:id/model. |
run_data | Objet RunHistory | Uniquement pour les tours pilotés par l’exécution d’un prompt enregistré, en plus des événements message. Voir Prompts et exécutions. |
{"type":"message","data":{"ID":90412,"isUser":false,"status":"generating","text":"Here are","...":"..."}}
{"type":"message","data":{"ID":90412,"isUser":false,"status":"generating","text":"Here are three options","...":"..."}}
{"type":"message","data":{"ID":90412,"isUser":false,"status":"finished","text":"Here are three options for ...","response_duration_ms":6210,"...":"..."}}
{"type":"ai_message_end"}
- Vos propres messages utilisateur ne vous sont pas renvoyés en écho sur votre connexion. La clé agit au nom de son propriétaire : un client piloté par une clé ne voit donc que les messages de l’IA et ceux des autres personnes.
- Tant qu’aucun client n’est connecté, les événements sont mis en mémoire tampon, rejoués à la connexion suivante, puis effacés. Un client qui se connecte longtemps après un tour peut d’abord recevoir des événements périmés de ce tour : ignorez les messages dont vous détenez déjà l’
IDdans un état terminé. - Les flux résident dans la mémoire du serveur d’API. Si vous êtes connecté sans rien recevoir pour un tour que vous savez en cours, rabattez-vous sur l’interrogation périodique de
GET /conversation/:id.
# 1. Start the turn without waiting
curl -X POST https://api.stickyprompts.com/api/v1/conversation/stream \
-H "Authorization: Bearer $STICKY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "message": "Summarise last week for the Northwind team.", "auto_model_type": "balanced" }'
# -> {"conversation_context_id":5120}
# 2. cURL cannot hold a WebSocket open; poll the newest messages instead
curl "https://api.stickyprompts.com/api/v1/conversation/5120?page=1&size=2" \
-H "Authorization: Bearer $STICKY_API_KEY"import asyncio, json, os, requests, websockets
KEY = os.environ["STICKY_API_KEY"]
BASE = "https://api.stickyprompts.com/api/v1"
start = requests.post(
f"{BASE}/conversation/stream",
headers={"Authorization": f"Bearer {KEY}"},
json={"message": "Summarise last week for the Northwind team.", "auto_model_type": "balanced"},
).json()
cid = start["conversation_context_id"]
async def listen():
url = f"wss://api.stickyprompts.com/api/v1/conversation/{cid}/ws"
async with websockets.connect(url, additional_headers={"Authorization": f"Bearer {KEY}"}) as ws:
async for frame in ws:
event = json.loads(frame)
if event["type"] == "message" and not event["data"]["isUser"]:
print(event["data"]["status"], len(event["data"]["text"]))
elif event["type"] == "error_message":
print("Failed:", event["data"]["error_text"], event["data"]["error_id"])
break
elif event["type"] == "ai_message_end":
break
asyncio.run(listen())import WebSocket from "ws"; // Node: browsers cannot send the Authorization header
const KEY = process.env.STICKY_API_KEY;
const BASE = "https://api.stickyprompts.com/api/v1";
const { conversation_context_id: cid } = await fetch(`${BASE}/conversation/stream`, {
method: "POST",
headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ message: "Summarise last week for the Northwind team.", auto_model_type: "balanced" }),
}).then((r) => r.json());
const ws = new WebSocket(`wss://api.stickyprompts.com/api/v1/conversation/${cid}/ws`, {
headers: { Authorization: `Bearer ${KEY}` },
});
ws.on("message", (raw) => {
const { type, data } = JSON.parse(raw);
if (type === "message" && !data.isUser) console.log(data.status, data.text.length);
if (type === "error_message") { console.error(data.error_text, data.error_id); ws.close(); }
if (type === "ai_message_end") ws.close();
});GET /conversation/:id/stream
/api/v1/conversation/:id/stream Un ancien endpoint Server-Sent Events. Utilisez plutôt le WebSocket ou l’interrogation périodique. Dans le code actuel, l’envoi de messages n’écrit que dans le WebSocket : ce flux ne transmet donc que les événements error_message et run_data liés aux erreurs d’exécution de prompts, et reste sinon ouvert sans envoyer le moindre contenu de message.
-
idinteger dans path obligatoire - ID numérique de la conversation.
Il renvoie 404 {"error":"Stream not found"} lorsque le serveur ne détient aucun flux en mémoire pour la conversation. Sinon, il répond avec Content-Type: text/event-stream et des trames event:<name>\ndata:<json>\n\n, où <name> vaut message, error_message (tableau de {run_id, error_id, error_text, model_name}), run_data (tableau de RunHistory) ou close (data: Stream closed).
Lire les conversations
GET /conversation/:id
/api/v1/conversation/:id Renvoie une conversation avec une page de ses messages, du plus récent au plus ancien. Les métadonnées de pagination figurent dans les headers de réponse X-Total-Count (nombre total de messages), X-Page et X-Page-Size.
-
idstring dans path obligatoire - ID de la conversation, slug, ou slug de partage public de la conversation.
-
pageinteger dans query facultatif par défaut1 - Numéro de page.
-
sizeinteger dans query facultatif par défaut10 - Messages par page.
Accès. Le propriétaire ; les utilisateurs disposant de chat_view ou chat_contribute par partage ; ou, lorsque :id est le slug public d’une conversation partagée, toute personne autorisée par le type de partage (public : tout le monde, internal : tout utilisateur connecté, workspace : les membres de l’espace de travail du propriétaire).
{
"credits_used": "0.4213",
"conversation_context_id": 5120,
"conversation_context_name": "Q4 newsletter subject lines",
"conversation_context_slug": "aB3dE5gH",
"expensive_warning_threshold": 1000,
"public_slug": null,
"share_type": "",
"is_public": false,
"user_name": "John Smith",
"messages": [
{ "ID": 90412, "isUser": false, "status": "finished", "text": "Here are three options ...", "...": "..." },
{ "ID": 90411, "isUser": true, "status": "finished", "text": "Draft three subject lines ...", "...": "..." }
],
"next_message_ai_model_id": 12,
"next_message_ai_model_style": "prompty",
"next_message_auto_model_type": null,
"next_message_reasoning_effort": null,
"has_sub_conversations": false,
"unsupported_files": null,
"current_user_permission": "chat_contribute",
"owner_id": 77,
"user_count": 1,
"team_shares": null,
"agent_id": null,
"invited_agents": [],
"is_agent_chat": false
}
| Champ | Signification |
|---|---|
credits_used | Crédits de toute la conversation, fils de comparaison compris (chaîne décimale). |
messages | Cette page de messages, du plus récent au plus ancien. Dans les messages de l’IA, les citations sont rendues dans text et l’original figure dans raw_text. |
next_message_ai_model_id, next_message_ai_model | Le modèle qu’utilisera le prochain tour. À défaut, celui du dernier message de l’IA. |
next_message_ai_model_style | Le style du prochain tour. Attention : la clé diffère de next_message_ai_style dans l’objet conversation. |
next_message_auto_model_type | best, balanced ou cheapest en cas de routage automatique. |
forked_from_conversation_id, _slug, _name | Renseignés sur les conversations dérivées (forks). |
has_sub_conversations | Une comparaison de modèles existe. |
unsupported_files | Fichiers joints précédemment que le prochain modèle ne sait pas lire. |
current_user_permission | chat_contribute pour le propriétaire, sinon votre accès le plus élevé : chat_view, chat_contribute ou none. |
team_shares | {team_id, team, access_type} pour chaque équipe avec laquelle la conversation est partagée. |
Erreurs. 403 {"error":"You are not allowed to access this conversation"}, 404 {"error":"Conversation not found"}.
GET /conversation
/api/v1/conversation Liste vos conversations de chat, de la plus récemment active à la plus ancienne. Seules les conversations de chat interactives comportant au moins un message y figurent.
-
pageinteger dans query facultatif par défaut1 - Numéro de page. Les totaux figurent dans les headers
X-Total-Count,X-PageetX-Page-Size. -
sizeinteger dans query facultatif par défaut10 - Éléments par page.
-
searchstring dans query facultatif - Recherche d’une sous-chaîne dans le texte de n’importe quel message ou dans le nom de la conversation.
-
agent_iduint dans query facultatif - Liste les chats de cet agent. Sans ce paramètre, les chats d’agent sont exclus.
-
team_iduint dans query facultatif - Liste les conversations partagées avec cette équipe avec
chat_contribute. Sans ce paramètre, vous obtenez les conversations qui vous appartiennent et qui ne sont pas des conversations d’équipe. -
X-Project-IDinteger dans header facultatif - Uniquement les conversations de ce projet.
Réponse. 200 avec un tableau d’objets conversation (vide : []). Chacun inclut user et project préchargés, message_count, credits_used et, dans messages, uniquement le dernier message (avec attachments vidé). Notez les clés en camelCase publicSlug, isPublic, userId, projectId, runId, isInteractive et forkedFromConversationId, à côté des clés en snake_case.
[
{
"ID": 5120, "CreatedAt": "2026-09-28T09:13:58Z", "UpdatedAt": "2026-09-28T09:14:10Z", "DeletedAt": null,
"slug": "aB3dE5gH", "publicSlug": null, "isPublic": false, "share_type": "",
"userId": 77, "user": { "ID": 77, "first_name": "John", "last_name": "Smith", "...": "..." },
"next_message_ai_model_id": 12, "next_message_ai_style": "prompty",
"next_message_auto_model_type": null, "next_message_reasoning_effort": null,
"projectId": null, "project": null, "agent_id": null,
"name": "Q4 newsletter subject lines", "source": "chat",
"messages": [ { "ID": 90412, "isUser": false, "text": "Here are three options ...", "...": "..." } ],
"isInteractive": true, "expensive_warning_threshold": 1000,
"forkedFromConversationId": null,
"message_count": 2, "credits_used": "0.4213"
}
]
GET /conversation/:id/used_prompts
/api/v1/conversation/:id/used_prompts Renvoie les prompts enregistrés distincts exécutés dans cette conversation, fils de comparaison compris : un tableau de { "id", "name", "slug", "ai_model_id", "user_id" }, ou []. L’ordre n’est pas défini.
-
idstring dans path obligatoire - ID ou slug de la conversation.
Gérer les conversations
PATCH /conversation/:id
/api/v1/conversation/:id Renomme une conversation et la place en tête de liste. Réservé au propriétaire.
-
idstring dans path obligatoire - ID ou slug de la conversation.
-
namestring obligatoire - Le nouveau nom. Vide ou absent, il provoque un
400.
Réponse. 200 avec l’objet conversation. Erreurs. 403 {"error":"You are not allowed to edit this conversation"}.
PATCH /conversation/:id/model
/api/v1/conversation/:id/model Définit le modèle, le style et le niveau de raisonnement des tours suivants. Autorisé pour le propriétaire et les utilisateurs disposant de chat_contribute. Diffuse aussi un événement WebSocket ai_model_change.
-
idstring dans path obligatoire - ID ou slug de la conversation.
-
ai_model_iduint facultatif - Modèle des tours suivants.
400 {"error":"AI model not found"}s’il est inconnu. -
ai_stylestring facultatif - Style des tours suivants.
-
auto_model_typestring facultatif best,balanced,cheapestou null. Toujours écrit : l’omettre ou envoyer null désactive le routage automatique. Envoyez-le à chaque appel pour rester en routage automatique.-
reasoning_effortstring facultatif - Ajusté aux niveaux pris en charge par le nouveau modèle ou par le modèle actuel.
Réponse. 200 {"message":"Model changed successfully"}. Erreurs. 400 {"error":"Cannot change model for agent conversations"}, 403 si vous n’avez pas l’accès.
POST /conversation/:id/fork
/api/v1/conversation/:id/fork Crée une nouvelle conversation nommée "Forked from <name>" contenant une copie de chaque message jusqu’à message_id inclus. Les pièces jointes, les outils et les enregistrements d’approbation MCP sont copiés, et les réglages de modèle, de style et de raisonnement sont conservés. La conversation source doit vous appartenir ou être partagée, sinon vous obtenez un 403.
-
idstring dans path obligatoire - ID ou slug de la conversation source.
-
message_iduint obligatoire - Le dernier message à copier. Il doit s’agir d’un message
normalde cette conversation ou de l’un de ses fils de comparaison (sinon404ou400).
Réponse. 200 avec une réponse de conversation réduite : conversation_context_id, conversation_context_name, conversation_context_slug, public_slug, is_public, user_name, messages (ici du plus ancien au plus récent) et credits_used: "0". Les autres clés contiennent leur valeur zéro.
DELETE /conversation/:id
/api/v1/conversation/:id Supprime de façon logique (soft delete) la conversation et ses messages, et masque ses exécutions de prompts dans l’historique des exécutions. Réservé au propriétaire.
-
idinteger dans path obligatoire - ID numérique de la conversation.
curl -X DELETE https://api.stickyprompts.com/api/v1/conversation/5120 \
-H "Authorization: Bearer $STICKY_API_KEY"
Réponse. 200 {"message":"Conversation deleted successfully"}. Erreurs. 404 {"error":"Conversation not found or you do not have permission to delete it"}.
POST /conversation/:id/retry
/api/v1/conversation/:id/retry Relance le dernier tour lorsque le dernier message de l’IA s’est soldé par une erreur. Le message en échec est régénéré sur place (même ID) avec le modèle et le style actuels de la conversation, ou avec ceux de l’agent. Réservé au propriétaire. Sans corps.
-
idstring dans path obligatoire - ID ou slug de la conversation.
Réponse. 200 avec :
- pour un tour de chat ordinaire, un Message. Sur les modèles avec
stream_support: true, l’appel rend la main aussitôt avec le message enstatus: "thinking", et le contenu arrive par le WebSocket ou par interrogation périodique ; sur les autres modèles, il renvoie le message terminé ; - pour un tour issu d’un prompt enregistré, un tableau d’objets RunHistory.
Erreurs. 400 {"error":"Last AI message does not have an error"}, 400 {"error":"No user message found in this conversation"}, 403, 500 {"error":"..."}.
POST /conversation/:id/snooze-expensive-warning
/api/v1/conversation/:id/snooze-expensive-warning Lorsque le credits_used d’une conversation dépasse son expensive_warning_threshold (1000 par défaut), l’application web affiche un avertissement d’utilisation. Cet appel double le seuil jusqu’à ce qu’il dépasse l’utilisation actuelle. Réservé au propriétaire.
-
idstring dans path obligatoire - ID ou slug de la conversation.
Réponse. 200 avec l’objet conversation et son nouveau expensive_warning_threshold. Erreurs. 400 si l’utilisation reste inférieure au seuil.
POST /conversation/:id/agents
/api/v1/conversation/:id/agents Invite l’un de vos agents dans la conversation pour qu’il puisse être mentionné (@mentioned). Réservé au propriétaire ; impossible dans les chats d’agent (400).
-
idstring dans path obligatoire - ID ou slug de la conversation.
-
agent_iduint obligatoire - Un agent qui vous appartient.
Réponse. 200 {"message":"Agent invited successfully"}. Erreurs. 404 {"error":"Agent not found or not owned by user"}, 403.
DELETE /conversation/:id/agents/:agentId
/api/v1/conversation/:id/agents/:agentId Retire un agent invité. Réservé au propriétaire.
-
idstring dans path obligatoire - ID ou slug de la conversation.
-
agentIdinteger dans path obligatoire - ID numérique de l’agent.
Réponse. 200 {"message":"Agent removed successfully"}. Erreurs. 400 {"error":"Invalid agent ID"}, 404.
Approbation des outils MCP
Cette section s’applique lorsqu’un tour utilise un serveur MCP distant (un outil remote_mcp, ou un agent doté de serveurs MCP) dont la configuration comporte require_approval: true, et que le modèle fonctionne sur le protocole OpenAI Responses, le seul qui produise des demandes d’approbation. Les exécutions de workflows approuvent toujours automatiquement.
- Le modèle demande à appeler un outil MCP. La génération s’interrompt et le message de l’IA reçoit, dans
mcp_approval_requests, une entrée par appel demandé. Sur le chemin de streaming, le texteApproval required for action: <name>, accompagné du libellé du serveur et des arguments, est aussi ajouté au texte du message. - Chaque entrée utilise comme clés les noms de champs Go (sans tags JSON).
Approved: nullsignifie que la demande est en attente ;trueoufalse, qu’elle a été tranchée.
{
"ID": 311, "CreatedAt": "2026-09-28T09:20:01Z", "UpdatedAt": "2026-09-28T09:20:01Z", "DeletedAt": null,
"ApprovalRequestID": "mcpr_abc123",
"Approved": null,
"ServerLabel": "crm",
"Name": "create_contact",
"Arguments": "{\"email\":\"jane@northwind.example\"}",
"MCPToolID": 0,
"MessageID": 90415
}
- Décidez avec
POST /conversation/:id/approve, en utilisant l’IDnumérique de l’entrée, et nonApprovalRequestID. - Le serveur enregistre la décision et lance un nouveau tour de l’IA qui la transmet au modèle. La suite est un nouveau message de l’IA.
POST /conversation/:id/approve
/api/v1/conversation/:id/approve Approuve ou rejette un appel d’outil MCP en attente.
-
idinteger dans path obligatoire - ID numérique de la conversation.
-
approval_request_iduint obligatoire - L’
IDde l’entrée dansmcp_approval_requests. -
is_approvedbool obligatoire truepour approuver,falsepour rejeter.-
use_streambool facultatif true: rend la main aussitôt ; la suite arrive par le WebSocket ou par interrogation périodique.false: attend la fin de la suite.
Réponse. 200 avec la chaîne JSON "Successfully handled approval", et non un objet. Le message de suite n’est pas renvoyé : lisez-le avec GET /conversation/:id ou par le WebSocket.
Erreurs. 404 {"error":"Conversation not found"}, 404 {"error":"MCP Approval request not found"}, 400 {"error":"Approval request already processed"}, 400 {"error":"No messages in conversation"}, 500. La suite utilise le modèle fixe défini pour le prochain message de la conversation ; ce fonctionnement n’est pas pris en charge sur une conversation en routage automatique.
Comparaison de modèles
Une sous-conversation exécute le même message sur deux modèles ou plus, côte à côte, avec un « fil » par modèle. Tant qu’elle est active, les messages de suivi envoyés à la conversation parente partent vers chaque fil. Sa clôture désigne un fil gagnant, dont l’historique se poursuit dans la conversation parente. C’est le pendant API de Comparer les modèles.
POST /conversation/:id/sub-conversation
/api/v1/conversation/:id/sub-conversation Lance une comparaison et attend la fin de chaque fil.
-
idstring dans path obligatoire - ID ou slug de votre conversation (réservé au propriétaire). Les valeurs littérales
nullouundefinedcréent d’abord une nouvelle conversation vide.
-
ai_model_idsuint[] obligatoire - Au moins 2 ID de modèles.
-
messagestring facultatif - Le message envoyé à chaque modèle.
-
prompt_instance_iduint facultatif - À la place de
message, exécute une instance de prompt enregistré dans chaque fil. -
attachmentsarray facultatif - Utilisé uniquement avec
prompt_instance_id. -
flash_modebool facultatif - Utilisé uniquement avec
prompt_instance_id. -
reasoning_effortstring facultatif - Utilisé uniquement avec
prompt_instance_id.
Le style est celui de la conversation, à défaut votre style préféré, à défaut prompty.
Réponse. 200 avec le Message conteneur (type: "sub_conversation"). Son sub_conversation contient parent_conversation_context_id, threads, selected_thread_id et is_active: true. Chaque fil comporte ai_model_id, ai_model, thread_conversation_context_id, thread_conversation_context (avec messages), unsupported_files et credits_used.
Erreurs. 400 avec moins de 2 modèles, 400 {"error":"AI model not found: <id>"}, 400 {"error":"An active sub-conversation already exists. Close it before creating a new one."}.
POST /conversation/:id/sub-conversation/stream
/api/v1/conversation/:id/sub-conversation/stream La variante en streaming : mêmes paramètres de chemin et même corps, mais l’appel rend la main dès que les messages utilisateur existent. Les réponses des fils sont ensuite diffusées sur le WebSocket de la conversation parente, et, dans la réponse, les messages de chaque fil ne contiennent que le message utilisateur.
POST /sub-conversation/:id/close
/api/v1/sub-conversation/:id/close Clôt une comparaison active dans une conversation qui vous appartient.
-
idinteger dans path obligatoire - ID numérique de la sous-conversation (
sub_conversation_idousub_conversation.ID).
-
ai_model_iduint obligatoire - Devient le modèle du prochain message de la conversation parente. Doit être supérieur à 0.
-
ai_stylestring facultatif - Devient le style de la conversation parente.
-
thread_iduint facultatif - Le fil gagnant.
0signifie aucun.
Réponse. 204 No Content. Erreurs. 404 si la comparaison est introuvable ou inactive.
POST /sub-conversation/:id/select-thread
/api/v1/sub-conversation/:id/select-thread Change le fil dont les messages constituent l’historique de la conversation. La sous-conversation doit être clôturée ; réservé au propriétaire.
-
idinteger dans path obligatoire - ID numérique de la sous-conversation.
-
thread_iduint obligatoire - Supérieur à 0.
Réponse. 204 No Content.
Partage
Les quatre endpoints de partage prennent l’ID numérique de la conversation et sont réservés au propriétaire (sinon 404 {"error":"Conversation not found"}).
POST /conversation/:id/share
/api/v1/conversation/:id/share Partage la conversation par lien. Génère un slug public de 32 caractères s’il n’en existe pas encore et définit isPublic: true. Lisez la conversation partagée avec GET /conversation/{public_slug}.
-
idinteger dans path obligatoire - ID numérique de la conversation.
-
share_typestring obligatoire workspace(membres de votre espace de travail),internal(tout utilisateur StickyPrompts connecté disposant du lien) oupublic(toute personne disposant du lien).
Réponse. 200 {"message":"Conversation shared successfully","publicSlug":"<32 chars>"}. Erreurs. 400 {"error":"Invalid share type"}.
POST /conversation/:id/revoke-share
/api/v1/conversation/:id/revoke-share Définit isPublic: false. Le slug est conservé. Sans corps.
-
idinteger dans path obligatoire - ID numérique de la conversation.
Réponse. 200 {"message":"Conversation share successfully revoked"}.
POST /conversation/:id/regenrate-share-slug
/api/v1/conversation/:id/regenrate-share-slug Remplace le slug public pour que les anciens liens cessent de fonctionner. Le chemin s’écrit bien regenrate, exactement comme indiqué. Sans corps.
-
idinteger dans path obligatoire - ID numérique de la conversation.
Réponse. 200 {"slug":"<new 32 chars>"}.
POST /conversation/:id/share-with-teams
/api/v1/conversation/:id/share-with-teams Partage la conversation en lecture seule avec vos équipes. La liste représente l’état souhaité complet pour vos équipes : toute équipe dont vous êtes membre et qui n’y figure pas perd le partage, sauf les équipes qui disposent déjà de chat_contribute (comme l’équipe pour laquelle une conversation d’équipe a été créée). L’appel garantit aussi l’existence d’un slug public.
-
idinteger dans path obligatoire - ID numérique de la conversation.
-
sharesarray obligatoire - Éléments
{ "team_id": uint, "access_type": "chat_view" | "none" }. Seulchat_viewpeut être accordé ici ;chat_contributeest refusé avec400.
Réponse. 200 {"message":"Conversation shared successfully with teams","publicSlug":"<32 chars>"}. Erreurs. 403 {"error":"You are not a member of team <name>"}, 404 pour les équipes inconnues.
Messages
POST /message/:id/export
/api/v1/message/:id/export Exporte un message dans un fichier DOCX ou PDF, soit sous forme de lien de téléchargement, soit directement dans une intégration de stockage connectée comme Google Drive. Vous devez être propriétaire de la conversation ou disposer au moins de chat_view sur celle-ci.
-
idinteger dans path obligatoire - ID numérique du message.
-
formatstring obligatoire docxoupdf.-
targetstring facultatif - Vide ou
local: produit un fichier téléchargeable. Sinon, l’identifiant d’un fournisseur de stockage connecté, par exemplegoogle_drive. -
folder_idstring facultatif - Dossier de destination chez le fournisseur. Obligatoire pour les cibles autres que locales.
-
namestring facultatif - Nom du fichier pour les cibles de type fournisseur (l’extension est ajoutée). Par défaut, le titre de la conversation.
Réponse. 200 avec exactement l’un des deux corps suivants :
{ "path": "https://<storage host>/<bucket>/<userId>/<random>.pdf" }
{ "entry": { "id": "...", "name": "Q4 subject lines.docx", "kind": "file", "mime_type": "...", "web_url": "...", "parent_id": "...", "...": "..." } }
Erreurs. 400 {"error":"invalid format"}, 400 {"error":"invalid folder_id"}, 400 {"error":"unknown export target"}, 403 {"error":"you are not allowed to export this message"} ou un dossier de destination non accessible en écriture, 404 si le message est introuvable ou l’intégration non connectée, 409 {"error":"reconnect_required"}, 501 si le fournisseur ne permet pas l’envoi de fichiers, 500.
Voir aussi
- Prompts et exécutions - exécuter des prompts enregistrés ; chaque exécution crée une conversation.
- Erreurs, pagination et quotas - formes des erreurs, motifs des
429et headers de pagination. - Référence des outils du serveur MCP -
send_message,get_conversation,list_conversations,delete_conversation.