Développeurs
API publique Beta
Créez des intégrations pour votre espace de travail avec des clés API sécurisées à portée limitée et un contrat JSON stable et versionné.
Ouvrir la référence interactive de l'APIDémarrage rapide
- 01
Ouvrir les clés API
Ouvrez Paramètres, sélectionnez Développeur, repérez Clés API, puis sélectionnez Créer une clé. Les propriétaires et les admins peuvent créer des clés.
- 02
Créer une clé API
Saisissez un Nom, choisissez Expire dans (jours), réglez Accès aux canaux sur Tous les canaux ou Canaux sélectionnés, et choisissez sous Portées les portées minimales dont votre intégration a besoin. Une requête n'aboutit que si la clé dispose exactement de l'action sur la ressource exigée par le point de terminaison. Sélectionnez Créer la clé.
- 03
Enregistrer votre clé API
La clé complète n'est affichée qu'une seule fois. Copiez-la dans votre gestionnaire de secrets, puis sélectionnez Je l'ai enregistrée.
- 04
Envoyer la clé
Utilisez un jeton Bearer, ou envoyez la même valeur dans
x-api-key. Ne placez jamais de clés dans les query strings ni dans du code exécuté par le navigateur.
cURL
curl https://www.usesonny.com/api/v1/contacts?limit=25 \
--header "Authorization: Bearer sonny_your_key"Des clés qui restent sécurisées
- Sécurité des clés
- Les clés utilisent le préfixe
sonny_, 64 caractères aléatoires, un hachage à sens unique au repos, une expiration configurable et une limite de 600 requêtes/minute par clé. Une clé est liée à un seul espace de travail. - Pour en révoquer une, sélectionnez le bouton corbeille à côté. Confirmez Révoquer la clé API ? en sélectionnant Supprimer. La clé cesse immédiatement de fonctionner.
- Autorisation à chaque appel
- Sonny vérifie le hachage et la portée, puis revérifie l'appartenance active du créateur à l'espace de travail, son rôle et l'état de facturation. Retirer ou désactiver cet utilisateur désactive immédiatement ses clés.
- Les canaux sélectionnés sont appliqués à chaque appel à l'API REST et à MCP. Les points de terminaison des contacts, des propriétés, des étiquettes et de gestion des webhooks exigent l'accès à tous les canaux. La création depuis un formulaire peut utiliser contacts:write avec conversations:write sur des canaux sélectionnés ; les points de terminaison de contacts autonomes restent à l'échelle de l'espace de travail.
Portées
contacts:readcontacts:writetags:readtags:writeconversations:readconversations:writemessages:readmessages:writemessages:sendwebhooks:readwebhooks:writekb:readkb:writecsat:readattachments:writemembers:readcontact-memory:readcontact-memory:writereporting:read
Ressources
- Contacts
- Gérez les contacts, les propriétés typées, les filtres sur valeur exacte et les souvenirs clients. Archivez un contact, ou effacez-le définitivement avec toutes ses conversations pour les demandes liées à la protection des données.
- Sources
- Découvrez les sources configurées et si chacune prend en charge le chat, l'e-mail ou les deux.
- Conversations
- Créez des demandes depuis des formulaires, filtrez ce qui demande de l'attention, attribuez des agents ou des équipes, reportez, étiquetez et mettez à jour par lots.
- Synchronisation
- Rejouez les changements durables de l'espace de travail et les traces de suppression avec un curseur enregistré.
- Membres et équipes
- Découvrez les collègues attribuables, leur disponibilité et leur accès effectif aux canaux.
- Rapports
- Lisez les rapports de support, d'équipe, d'IA, de connaissances, de prospects et de disponibilité.
- Messages
- Lisez l'historique des messages et l'extraction des pièces jointes, importez des fichiers privés, ajoutez des notes internes, et envoyez ou modifiez des réponses aux clients.
- Webhooks
- Gérez les points de terminaison, les abonnements, les tests, les livraisons et les nouvelles tentatives.
- Base de connaissances
- Créez, lisez, mettez à jour et supprimez les articles et catégories du centre d'aide, par source.
- Satisfaction client
- Lisez les scores CSAT de l'espace de travail, de chaque canal et de chaque conversation, et listez les notes individuelles filtrées par valeur, commentaire, responsable ou période.
Utiliser Sonny depuis un outil IA
Sonny MCP expose chaque opération de l'API publique sous forme d'outil. Les clients se connectent avec OAuth 2.1 — ou avec une clé API à portée limitée — et chaque appel conserve les mêmes portées, frontières d'espace de travail et règles métier.
Lire le guide Sonny MCPRéponses et erreurs
Les réponses de collection utilisent data et incluent la pagination le cas échéant. Chaque réponse inclut x-request-id ; vous pouvez fournir un identifiant de requête sûr et Sonny le renverra. Les erreurs renvoient un message sûr, sans exposer de détails d'implémentation sensibles.
{
"error": {
"type": "validation_error",
"message": "Invalid email address",
"requestId": "req_01J..."
}
}400- Entrée, JSON, requête ou curseur invalide.
401- Clé API manquante, invalide, expirée ou sans la portée requise.
402- L'état de facturation de l'espace de travail bloque cette requête.
403- Le rôle du créateur de la clé dans l'espace de travail n'est pas autorisé.
404- La ressource n'existe pas dans l'espace de travail de la clé.
409- La requête entre en conflit avec une ressource existante.
410- Curseur de synchronisation expiré. Rechargez l'état actuel et rejouez depuis un nouveau curseur.
413- Le fichier importé dépasse la taille autorisée.
422- La source n'a pas de canal e-mail ou une valeur de champ envoyée est invalide.
429- La limite de débit par clé a été dépassée.
500- Une erreur inattendue s'est produite. Réessayez avec l'identifiant de requête.
503- La file de livraison des webhooks est saturée. Réessayez plus tard.
Limites de débit
Chaque clé API peut effectuer jusqu'à 600 requêtes par minute. Chaque réponse indique la fenêtre en cours via les en-têtes standard RateLimit-Limit, RateLimit-Remaining et RateLimit-Reset, pour que les clients puissent se réguler eux-mêmes au lieu de deviner. En cas de dépassement, l'API renvoie 429 avec un en-tête Retry-After — attendez ce nombre de secondes avant de réessayer.
Versionnage et dépréciation
L'API est versionnée dans le chemin de l'URL (/api/v1). Au sein d'une version, nous n'apportons que des changements additifs — nouveaux points de terminaison, nouveaux champs optionnels, nouvelles valeurs d'énumération. Les changements incompatibles arrivent dans une nouvelle version, et avant de retirer un point de terminaison v1, nous prévenons au moins six mois à l'avance : sur cette page, par e-mail aux propriétaires d'espaces de travail disposant de clés API actives, et via les en-têtes Deprecation et Sunset sur les points de terminaison concernés.
Modifier une réponse envoyée
- Donnez à votre clé API ou à votre connexion MCP les portées
messages:readetmessages:sendainsi que l'accès au canal de la réponse. - Lisez les messages de la conversation et copiez l'identifiant d'une réponse humaine que vous avez envoyée. Une clé API agit au nom de son créateur ; OAuth agit au nom du collègue connecté.
- Envoyez le texte de remplacement avec la requête ci-dessous, ou appelez
edit_messagedans MCP avecconversationId,messageIdetbody. - Vérifiez le message renvoyé. Son identifiant, ses pièces jointes, son accusé de lecture et son heure d'envoi d'origine restent inchangés.
curl --request PATCH \
https://www.usesonny.com/api/v1/conversations/conversation_1/messages/message_1 \
--header "Authorization: Bearer sonny_your_key" \
--header "Content-Type: application/json" \
--data '{"body":"The corrected reply"}'La modification corrige la transcription et les clients de chat connectés. Elle n'envoie ni nouvel e-mail ni notification, et les e-mails déjà distribués restent inchangés. Seules vos propres réponses humaines aux clients peuvent être modifiées ; les messages entrants, les réponses de bot, les notes internes et les réponses des autres collègues ne le peuvent pas. Attendez la fin de l'envoi d'un e-mail en cours avant de modifier. Le texte de remplacement doit contenir de 1 à 50 000 caractères ; le HTML et les aperçus de liens précédents sont effacés. Les intégrations reçoivent un webhook message.updated et un événement de synchronisation. Interroger uniquement les identifiants de messages plus récents ne détectera pas les modifications ; utilisez le flux de synchronisation durable.
Créer une conversation depuis un formulaire
Envoyez une soumission de formulaire à POST /api/v1/conversations. Sonny trouve ou crée le contact à partir de l'e-mail, enregistre les réponses et ouvre une conversation entrante sur le canal e-mail de la source choisie. L'équipe, les règles d'attribution et les notifications du canal s'appliquent. Les agents répondent par e-mail.
- Créez une clé avec
conversations:writeetcontacts:write. Vous pouvez la limiter aux canaux sélectionnés du client. Trouvez l'identifiant de la source avecGET /api/v1/sources, qui nécessite aussiconversations:read. - Dans n8n, ajoutez un nœud HTTP Request : méthode POST, URL
https://www.usesonny.com/api/v1/conversations. Stockez la clé dans un identifiant Header Auth :Authorizationavec la valeurBearer sonny_your_key. - Activez Send Body, choisissez JSON et Using JSON, puis basculez tout le champ JSON en Expression et collez cet exemple. Remplacez l'identifiant de la source et associez les champs d'entrée à votre formulaire. Utilisez l'identifiant de soumission stable et unique du formulaire, pour qu'une nouvelle tentative réutilise la même valeur.
{{ {
sourceId: "YOUR_CLIENT_SOURCE_ID",
contact: { email: $json.email, name: $json.name },
subject: "Website enquiry",
message: $json.message,
fields: {
Company: String($json.company ?? ""),
Budget: String($json.budget ?? ""),
Service: String($json.service ?? "")
},
externalId: "website-form-" + $json.submissionId
} }}Pour plus d'options de nœud, consultez le guide HTTP Request de n8n. L'outil MCP équivalent est create_conversation, avec la même charge utile et les mêmes permissions.
Les nouveaux noms de champs deviennent des propriétés texte. Les champs nombre, URL, date et liste existants doivent recevoir des valeurs texte valides ; une valeur incorrecte renvoie 422 en nommant le champ et rien n'est enregistré. Les dates acceptent les dates ISO ou les horodatages ; les valeurs de liste doivent correspondre à une option. Jusqu'à 50 champs sont acceptés, avec des noms de 100 caractères maximum et des valeurs de 5 000 caractères maximum. Les propriétés apparaissent sur le contact et dans la barre latérale de la conversation. Les deux corps de message conservent une copie des réponses, y compris lorsque vous fournissez le champ optionnel htmlMessage.
Le champ optionnel tags accepte jusqu'à 20 identifiants d'étiquettes existantes de l'espace de travail. La réponse contient conversation, un résumé du contact, message et deduplicated. Les nouvelles soumissions renvoient 201. Réutiliser externalId sur la même source renvoie 200 avec les identifiants d'origine et deduplicated: true ; le contenu modifié est ignoré. Sans identifiant externe, chaque appel crée une nouvelle conversation. Les pièces jointes à la création et les réponses automatiques de l'IA ne sont pas prises en charge.
Workflows d'agent
Trier, agir et rester synchronisé
REST et MCP partagent les mêmes permissions et les mêmes workflows. Les identifiants ne peuvent que restreindre votre accès actuel aux canaux ; retirer un canal de votre appartenance le retire aussi de vos intégrations.
Trouver les conversations qui demandent de l'attention
Filtrez par awaitingReply, unread, unassigned, assigneeId, agentGroupId, snoozed, priority ou tagIds. awaitingReply ignore les notes internes ; unread est propre au collègue authentifié. unassigned signifie sans responsable individuel, même si une équipe est attribuée. Les étiquettes correspondent à n'importe lequel des identifiants fournis.
GET /api/v1/conversations?status=open&awaitingReply=true&compact=true&sort=waitingSince&direction=ascTriez par waitingSince, lastMessageAt, createdAt ou priorité métier, avec la direction asc ou desc. Les identifiants départagent les égalités. Les filtres omis conservent compact=false et snoozed=any. En REST, tagIds accepte des identifiants séparés par des virgules ; MCP accepte aussi un tableau. waitingSince démarre au premier message entrant après la dernière réponse ; les relances et les notes internes ne le réinitialisent pas. Lancez cette analyse de la file d'attente de façon planifiée, même quand aucun webhook n'arrive, pour faire ressortir les anciens fils.
Rattraper son retard sans relire la boîte de réception
Utilisez GET /api/v1/sync avec conversations:read. Le flux durable inclut les changements de conversations, les étiquettes, les messages, les propriétés de contact, les souvenirs et les traces de suppression. Chaque charge utile exige aussi sa propre portée de lecture : le corps des messages nécessite messages:read et les souvenirs contact-memory:read. Les identifiants restreints ne reçoivent que les canaux autorisés.
- Commencez sans curseur, suivez nextCursor jusqu'à ce que hasMore soit false, puis enregistrez ce curseur.
- Lisez les listes actuelles de conversations et de contacts, ainsi que l'historique nécessaire à votre état initial.
- Rejouez depuis le curseur enregistré pour récupérer les changements survenus pendant cette lecture. Traitez chaque page, puis enregistrez nextCursor.
Dédupliquez par id d'événement : la relecture garantit au moins une livraison, donc les actions en aval doivent avoir leur propre protection contre les doublons. Une requête sans curseur couvre la dernière heure, pas un instantané complet. Les événements sont conservés 30 jours ; un HTTP 410 resync_required signifie qu'il faut tout recharger. Rechargez aussi après avoir élargi les portées ou l'accès aux canaux. Utilisez limit jusqu'à 100 et maxBodyChars jusqu'à 10 000 (500 par défaut). Définissez compact=true pour obtenir les champs de message textPreview/textTruncated limités à 200 caractères au lieu de body/bodyTruncated. Les webhooks peuvent réveiller un agent ; le flux reste disponible sans abonnement aux webhooks ou lorsque la livraison des webhooks prend du retard.
Enregistrer une vérification une fois et partager le résultat
Avant de recommencer une investigation, lisez list_conversation_checks (GET /api/v1/conversations/{conversationId}/checks). Enregistrez un résultat avec record_conversation_check (PUT sur le même chemin), en fournissant key, result, checkedBy et une reference optionnelle pour l'identifiant ou l'URL de la carte. Par exemple : key=product-version, result=Shopstar Go verified, checkedBy=Engineer, reference=card-X. Sonny enregistre l'actorId authentifié et l'horodatage checkedAt. Réutiliser une key remplace uniquement cette vérification ; il s'agit d'un état actuel, pas d'un historique. Les lectures nécessitent conversations:read et les écritures conversations:write, toutes deux limitées au canal de la conversation. Ces appels n'envoient pas de réponse et ne marquent pas le vendeur comme ayant répondu.
Attribuer et mettre à jour le travail par lots
Découvrez les collègues et équipes actifs et attribuables avec GET /api/v1/members and /teams (members:read). Les réponses incluent la disponibilité et l'accès effectif aux canaux, sans les adresses e-mail. Utilisez conversations:write pour modifier status, priority, assigneeId, agentGroupId, snoozedUntil, snoozedUntilReply, addTagIds ou removeTagIds.
POST /api/v1/conversations/batch
{
"conversationIds": ["conversation_1", "conversation_2"],
"updates": { "agentGroupId": "team_1", "assignment": "round_robin" }
}Le tourniquet choisit un membre d'équipe disponible qui a accès au canal de la conversation. Sans membre éligible, une mise à jour individuelle renvoie 409 et un élément de lot échoue. Chaque lot accepte jusqu'à 100 identifiants uniques et applique un correctif de façon atomique par conversation. Examinez chaque résultat { id, ok, error? } ; certains éléments peuvent échouer. Les lots utilisent la limite de débit actuelle par requête, sans décompte pondéré selon le nombre d'éléments.
Partager le contexte client avec Sonny AI
Listez, enregistrez et supprimez les souvenirs de contact avec contact-memory:read/write. Fournissez à la fois contactId et un sourceId accessible ; le contact doit avoir une conversation sur cette source. Les faits enregistrés suivent la même validation, la même gestion des doublons et les mêmes limites que l'application, et sont enregistrés comme souvenirs manuels.
Lisez les définitions de propriétés sur /api/v1/properties et lisez ou définissez les valeurs sur /api/v1/contacts/{contactId}/properties. MCP expose list_properties, get_contact_properties et set_contact_property. Ils nécessitent contacts:read/write et l'accès à tous les canaux. Définissez exactement un propertyId ou un propertyName, avec une valeur texte ou null pour l'effacer. Les valeurs texte, nombre, URL, date et liste sont validées par rapport à la définition du champ.
PUT /api/v1/contacts/contact_1/properties
{ "propertyName": "Plan", "value": "Pro" }
GET /api/v1/contacts?property[Plan]=ProLes filtres de propriétés correspondent aux chaînes stockées exactes ; plusieurs propriétés doivent toutes correspondre. Les valeurs écrites via l'API sont signalées comme données API dans Co-Pilot et le répondeur automatique. Les règles existantes sur les clients vérifiés et les sources s'appliquent toujours. Les valeurs de champs internes saisies manuellement restent exclues de ce contexte IA.
Lire les mêmes rapports que votre équipe
Avec reporting:read, appelez GET /api/v1/reporting/{kind}. Les types sont overview, volume, response-times, agents, sources, tags, csat, ai, knowledge, leads et online-hours. overview combine les totaux, les temps de réponse et le CSAT. Les filtres sont period (1 à 365 jours, 30 par défaut), les dates from/to appariées (to est exclusif), granularity (day/month), source, assigneeId et tagId. source accepte all, all-chat, all-email, website:{id} ou email:{id}.
Les rapports utilisent les requêtes du tableau de bord et les contrôles d'accès actuels. knowledge utilise les dates et les canaux autorisés, indépendamment de la source, du responsable ou de l'étiquette sélectionnés. online-hours mesure la présence des collègues accessibles dans l'espace de travail ; ses totaux de conversations restent limités aux canaux. Les points de terminaison /csat existants conservent leur portée distincte csat:read et peuvent décrire une population différente.
Envoyer des fichiers avec des réponses ou des notes internes
Accordez attachments:write et importez un fichier de 25 Mo maximum pour une conversation. POST /api/v1/attachments prend les champs multipart file et conversationId. La réponse contient un id et expiresAt. Passez jusqu'à 10 attachmentIds à une réponse ou une note dans l'heure. Chaque fichier importé est lié à votre utilisateur et à la conversation et ne peut être utilisé qu'une seule fois. Les fichiers inutilisés sont nettoyés après expiration.
POST /api/v1/conversations/conversation_1/reply
{ "attachmentIds": ["upload_1"] }Les réponses nécessitent messages:send ; les notes internes nécessitent messages:write et n'atteignent jamais les clients. Les messages contenant uniquement des pièces jointes sont pris en charge. Les réponses par e-mail incluent les fichiers dans la limite de taille de l'e-mail et des liens de téléchargement pour le reste ; les e-mails de chat hors ligne incluent des liens vers les fichiers. Les liens envoyés par e-mail restent utilisables tant que la pièce jointe existe, pour que les destinataires puissent les ouvrir plus tard. Transférer l'e-mail partage l'accès à ces fichiers. Consultez emailDeliveryStatus pour les échecs de livraison.
Les lectures de messages autorisées incluent downloadUrl, downloadExpiresAt, aiStatus, aiDescription et aiExtractedText, ainsi que videoTranscripts pour les vidéos liées (Loom, Vimeo et autres). Les liens de téléchargement durent 15 minutes ; relisez le message pour obtenir des liens frais. Les nouveaux fichiers importés via l'API/MCP sont stockés en privé. Les anciennes pièces jointes restent publiques et sont marquées access=legacy_public : leur URL d'origine n'expire pas. Lire un message lance la lecture de ses images lorsque l'espace de travail dispose de Sonny AI. Les lectures d'images et les transcriptions vidéo se terminent peu après l'arrivée d'un message : tant qu'elles sont en cours, la réponse commence par readsInProgress, dont nextStep indique l'appel exact à effectuer. Passez waitSeconds (jusqu'à 30) pour les attendre en une seule requête. Les messages du widget destinés aux clients et les messages en temps réel n'incluent jamais d'extraction ni de transcription.
Base de connaissances
Synchroniser depuis une source externe
Synchronisez articles et catégories avec des identifiants externes stables, importez du Markdown ou du HTML, importez des images, définissez l'ordre et gérez les audiences de lecteurs. Répéter un upsert met à jour le contenu existant.
- Choisissez le sourceId de votre canal et accordez kb:read et kb:write. Gardez la clé API sur votre serveur et limitez son accès aux canaux.
- Créez la catégorie, puis synchronisez un article en brouillon. Vérifiez sa mise en forme et ses accès avant de le publier.
- Configurez l'accès au centre d'aide, publiez et testez la vue lecteur. Utilisez la pagination et des identifiants externes stables pour les mises à jour ultérieures.
Gérer les audiences clients
Créez des groupes à partir d'attributs de clients vérifiés et appliquez-les à un centre d'aide, une catégorie ou un article. Toutes les restrictions héritées doivent correspondre. Les identifiants API et MCP agissent en tant que membres de l'équipe dans les limites de leurs portées ; prévisualisez et testez une vraie session client pour vérifier l'accès des lecteurs.
Configurer et tester les audiences du centre d'aideDocumentation associée
- Sonny MCPBeta
Connectez des assistants IA aux workflows de la boîte de réception, aux souvenirs clients, aux rapports et aux fichiers via OAuth ou des clés à portée limitée.
- WebhooksBeta
Abonnez-vous aux événements signés de l'espace de travail et inspectez les tentatives de livraison.
- Contacts
Découvrez comment les contacts sont créés, gérés, étiquetés et fusionnés dans Sonny.
- Boîte de réception
Comprenez les statuts, les priorités, l'attribution, le report, les actions groupées et les raccourcis clavier.