Écrire par SMS, WhatsApp, chat ou note
Écrire à une personne dans sa conversation — un SMS, un message WhatsApp, un message de chat ou une note interne —, et savoir qui chaque média peut joindre.
Tout échange avec une personne vit dans une conversation : emails, SMS, messages WhatsApp, chat, notes internes et appels s'y suivent dans un même fil. Chaque personne — un contact, un collègue — a sa conversation par défaut : c'est là que vous lui écrivez, et là que se rangent vos échanges avec elle.
Le compositeur de la conversation écrit un SMS, un message WhatsApp ou une note interne ; il écrit aussi un email (Media 1,
avec un objet), mais un email tiré d'un modèle, avec ses pièces jointes, se compose comme dans Envoyer un email.
Le chat a sa propre route.
1Ouvrir la conversation de la personne
POST https://staging-api.docage.com/Conversations/DefaultWithPerson?contactId=9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…curl -X POST "https://staging-api.docage.com/Conversations/DefaultWithPerson?contactId=9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…"using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Post, "https://staging-api.docage.com/Conversations/DefaultWithPerson?contactId=9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
using HttpResponseMessage response = await client.SendAsync(request);
string result = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
throw new HttpRequestException(result);const response = await fetch("https://staging-api.docage.com/Conversations/DefaultWithPerson?contactId=9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`
}
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;contactIdpour un contact,docageUserIdpour un collègue : l'un ou l'autre, jamais les deux.- La conversation est créée si elle n'existe pas encore, ou si la précédente est fermée.
- La réponse est son résumé : gardez son
Id.CanWritedit si vous pouvez y écrire. 400: aucune personne, ou les deux ; vous-même ; une personne qui n'est pas de votre organisation.
2Lire ce que la conversation permet
GET https://staging-api.docage.com/Conversations/4d1c8e52-0000-4000-8000-000000000101/ComposeOptions
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…curl "https://staging-api.docage.com/Conversations/4d1c8e52-0000-4000-8000-000000000101/ComposeOptions" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…"using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Get, "https://staging-api.docage.com/Conversations/4d1c8e52-0000-4000-8000-000000000101/ComposeOptions");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
using HttpResponseMessage response = await client.SendAsync(request);
string result = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
throw new HttpRequestException(result);const response = await fetch("https://staging-api.docage.com/Conversations/4d1c8e52-0000-4000-8000-000000000101/ComposeOptions", {
headers: {
Authorization: `Bearer ${token}`
}
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;Recipients: les participants que vous pouvez viser, vous excepté. Chacun a sa clé (Key) :c:suivi de l'identifiant d'un contact,s:d'une société,a:d'une adresse sans fiche,u:d'un collègue.HasMobiledit si un SMS ou un message WhatsApp le joint,HasEmailsi un email le joint ;IsColleaguemarque un collègue.SmsTemplates: les modèles de SMS.WhatsAppAccountsetDefaultWhatsAppAccountId: les comptes WhatsApp que vous pouvez employer, et celui d'office — le compte du dernier message WhatsApp de la conversation s'il vous est encore proposé, sinon le seul compte proposé ; vide s'il y en a plusieurs.WhatsAppTemplates: les modèles WhatsApp ;IsApprovedmarque ceux qui partent tels quels.WhatsAppWindowEndsAtUtc: la fin de la fenêtre de 24 heures de WhatsApp (voir l'étape 4).
404 : la conversation est introuvable, ou vous ne la lisez pas — la même réponse. 403 : vous la lisez sans pouvoir y écrire.
3Envoyer un SMS
Le compositeur reçoit un formulaire :
curl -X POST "https://staging-api.docage.com/Conversations/4d1c8e52-0000-4000-8000-000000000101/Compose" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…" \
-F "Media=2" \
-F "BodyText=Bonjour Camille, votre dossier est prêt : passez quand vous voulez." \
-F "RecipientKeys=c:9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f"Media:2SMS,3WhatsApp,4note interne ;1email.RecipientKeys: un champ par destinataire, choisi parmi les participants. Sans lui : les correspondants extérieurs qui ont un mobile.TemplateId: un modèle deSmsTemplates; son texte part quandBodyTextest vide.- Le texte part tel quel : un champ
{{…}}y est refusé, sauf{{MessageSignature}}, remplacé par la signature SMS par défaut de l'utilisateur (par rien s'il n'en a pas). IsMarketing: un SMS commercial porte la mention STOP, et ne part pas vers un numéro désabonné.- Un SMS part pour chaque destinataire. Chacun est facturé, au message et non au segment.
4Envoyer un message WhatsApp
curl -X POST "https://staging-api.docage.com/Conversations/4d1c8e52-0000-4000-8000-000000000101/Compose" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…" \
-F "Media=3" \
-F "BodyText=Bonjour Camille, votre rendez-vous de jeudi est confirmé." \
-F "WhatsAppAccountId=2e8f6b31-0000-4000-8000-000000000301"WhatsAppAccountId: le compte d'envoi. Sans lui : le compte du modèle choisi, sinon le compte d'office, celui queDefaultWhatsAppAccountIdannonce dans les options ; sans aucun — plusieurs comptes et aucun message WhatsApp dans la conversation —, l'envoi est refusé (400).- La fenêtre de 24 heures : WhatsApp n'accepte un texte libre que dans les 24 heures qui suivent le dernier message reçu de la
personne (
WhatsAppWindowEndsAtUtc). Au-delà, ou sans message reçu, seul un modèle approuvé part :TemplateId, un modèle deWhatsAppTemplatesdontIsApprovedest vrai. Il part tel quel, son texte à la place deBodyText. - Un texte libre part tel quel : un champ
{{…}}y est refusé. - Chaque message parti est facturé.
5Écrire en chat
curl -X POST "https://staging-api.docage.com/Conversations/4d1c8e52-0000-4000-8000-000000000101/Messages" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…" \
-F "bodyText=Tu peux relire le devis Dupont avant 17 h ?" \
-F "clientMessageId=6f4b2d10-0000-4000-8000-000000000401"bodyText: 10 000 caractères au plus. Des fichiers partent dans le même formulaire, si la conversation les permet (AllowAttachmentsde son résumé) ; 50 Mo au plus par requête.clientMessageId: l'identifiant que vous donnez au message. Renvoyé avec le même, il n'est pas doublé — voir Rejouer une requête sans doublon.- La réponse est le message enregistré, tel que les autres participants le reçoivent.
400: un message vide ou trop long, une pièce jointe que la conversation refuse.403: vous lisez la conversation sans pouvoir y écrire.404: la conversation est introuvable, ou vous ne la lisez pas — la même réponse.409: la conversation est fermée ; elle se rouvre parPOST https://staging-api.docage.com/Conversations/{id}/Reopen.
Un contact lit le chat sur la page de la conversation, sans compte, par un lien personnel valable trente jours. Pour le lui envoyer :
POST https://staging-api.docage.com/Conversations/4d1c8e52-0000-4000-8000-000000000101/Invitations
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…
Content-Type: application/json
{ "ContactId": "9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f", "Channel": 1 }curl -X POST "https://staging-api.docage.com/Conversations/4d1c8e52-0000-4000-8000-000000000101/Invitations" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…" \
-H "Content-Type: application/json" \
-d '{
"ContactId": "9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f",
"Channel": 1
}'using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Post, "https://staging-api.docage.com/Conversations/4d1c8e52-0000-4000-8000-000000000101/Invitations");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = new StringContent("""
{
"ContactId": "9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f",
"Channel": 1
}
""", Encoding.UTF8, "application/json");
using HttpResponseMessage response = await client.SendAsync(request);
string result = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
throw new HttpRequestException(result);const response = await fetch("https://staging-api.docage.com/Conversations/4d1c8e52-0000-4000-8000-000000000101/Invitations", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"ContactId": "9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f",
"Channel": 1
})
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;Channel : 1 par email (d'office), 2 par SMS — un SMS facturé, refusé tant que l'organisation n'est pas en production. 400 :
une conversation directe entre collègues (ouvrez plutôt un groupe), un contact d'une autre organisation, un contact sans adresse
email ou sans mobile selon le moyen choisi. 403 : vous lisez la conversation sans pouvoir y écrire. 404 : la conversation est
introuvable, ou vous ne la lisez pas.
6Poser une note interne
curl -X POST "https://staging-api.docage.com/Conversations/4d1c8e52-0000-4000-8000-000000000101/Compose" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…" \
-F "Media=4" \
-F "BodyText=Rappelée ce matin : elle préfère être contactée l'après-midi." \
-F "ClientMessageId=6f4b2d10-0000-4000-8000-000000000402"Une note reste dans l'équipe : elle ne part chez personne, et la personne ne la voit jamais. Elle se pose dans une conversation avec un
correspondant extérieur ; entre collègues, elle est refusée. 10 000 caractères au plus ; ClientMessageId la protège du doublon.
7Ce que rend le compositeur
Le message écrit : son Id, son Media et son statut, Status — 1 en attente, 2 envoyé, 3 remis, 5 en erreur. Il est
aussitôt dans le fil : voir Lire les échanges d'une conversation.
Les refus du compositeur : 404 pour une conversation introuvable, ou que vous ne lisez pas — la même réponse ; 403 si vous la
lisez sans pouvoir y écrire, ou si le module du média est fermé à votre organisation ; 400 pour tout autre refus de l'envoi, avec sa
raison.
Les pièges
- Un destinataire se choisit parmi les participants. Une clé qui ne désigne aucun participant, ou un destinataire que le média
ne joint pas — sans mobile, un collègue par SMS ou par WhatsApp —, fait refuser l'envoi (
400), avec sa raison : un message ne part jamais à moins de personnes que demandé. Pour écrire à une autre personne, ouvrez sa conversation par défaut. - Hors production, un SMS est refusé — il reste dans le fil, en erreur, avec ce motif : voir Environnement d'essai.
- Un module fermé refuse son média :
403pour un SMS sans le module SMS, un message WhatsApp sans le module WhatsApp, un email sans le module Emails. - Un envoi refusé reste au fil. Le message est rangé dans la conversation avant de partir : un refus — de l'opérateur ou de
WhatsApp (numéro refusé, fenêtre de 24 heures passée), ou avant eux (numéro invalide, organisation hors production, numéro
désabonné d'un SMS commercial) — rend
400avec son motif, et le message reste dans le fil, en erreur (Status5) ; la fiche du SMS ou du message WhatsApp porte le même motif. Relisez le fil avant de réécrire. - Seuls le chat et la note se protègent du doublon. Un SMS ou un message WhatsApp renvoyé repart, et se facture de nouveau.