Développeurs

Sonny MCP Beta

Connectez à votre espace de travail des assistants IA compatibles MCP — Claude, et tout client qui parle le Model Context Protocol — avec les mêmes portées et les mêmes limites que l'API publique.

Lire le guide de l'API publique

Démarrage rapide

  1. 01

    Ajouter Sonny à Claude

    Dans Claude ou Cowork, ajoutez un connecteur personnalisé avec l'URL https://www.usesonny.com/api/mcp. Sonny prend en charge l'enregistrement automatique des clients : aucun identifiant ni secret client à copier.

  2. 02

    Approuver l'accès à l'espace de travail

    Claude ouvre Sonny dans votre navigateur. Connectez-vous, vérifiez les permissions demandées et choisissez l'espace de travail à connecter. OAuth 2.1 avec PKCE limite les jetons d'accès et de rafraîchissement obtenus à cette approbation.

  3. 03

    Demander à votre assistant d'utiliser Sonny

    Les outils se décrivent eux-mêmes : une demande comme « Liste mes conversations ouvertes » suffit. Les assistants voient quels outils sont en lecture seule et lesquels sont destructifs, donc un bon client demande avant de modifier quoi que ce soit.

Claude Code

claude mcp add --transport http sonny https://www.usesonny.com/api/mcp

Configuration JSON du client

{
  "mcpServers": {
    "sonny": {
      "url": "https://www.usesonny.com/api/mcp"
    }
  }
}

Compatibilité avec les clés API

Si un client ne peut pas mener à bien OAuth, créez une clé à portée limitée dans Paramètres → Développeur et envoyez-la dans un en-tête Authorization Bearer. Les clés API restent entièrement prises en charge pour les échanges de serveur à serveur et les anciens clients.

"Authorization": "Bearer sonny_your_key"

Comment Sonny sécurise les appels d'outils

Un espace de travail, des portées choisies
Chaque appel s'exécute dans l'espace de travail choisi lors du consentement OAuth ou dans celui qui possède la clé API. Un outil ne fonctionne que si son identifiant dispose de la portée requise.
Des annotations d'outils fiables
Les outils en lecture seule sont marqués comme tels ; les outils de mise à jour et de suppression sont marqués destructifs pour que votre client puisse demander confirmation avant d'agir.
Les mêmes règles métier
Les outils exécutent exactement les mêmes workflows que l'API publique — historique d'audit, notifications et webhooks se comportent comme si un collègue avait effectué la modification.

Garder un assistant dans une seule boîte de réception

Les canaux sélectionnés sur une clé API sont automatiquement appliqués à chaque appel d'outil. Les clés API et les connexions OAuth suivent aussi l'accès actuel aux canaux du collègue connecté. Pour les connexions OAuth ou les clés ayant accès à tous les canaux, les espaces de travail contiennent souvent plusieurs sources — une par produit ou par marque. Demandez à votre assistant d'appeler list_sources une fois pour les découvrir, puis de passer sourceId à list_conversations : les questions sur un produit ne renverront alors que les conversations de ce produit. Chaque conversation porte aussi son propre sourceId, ce qui rend les résultats vérifiables.

Faire tourner une boucle de support peu coûteuse

  1. Découvrir les changements : initialisez avec le flux durable sync, enregistrez nextCursor après le traitement de chaque page et dédupliquez les identifiants d'événements. Pour choisir le travail, appelez list_conversations avec sourceId, awaitingReply: true, snoozed: "false" et compact: true. Les notes internes ne masquent pas les messages clients sans réponse.
  2. Ne lire que le nouveau texte : pour chaque conversation modifiée, appelez list_messages avec votre dernier identifiant de message ou horodatage ISO dans after et définissez includeHtml: false, sauf si le HTML de l'e-mail est vraiment nécessaire.
  3. Attendre les images et les vidéos : quand list_messages renvoie readsInProgress, effectuez l'appel indiqué dans son nextStep. Son waitSeconds retient la réponse jusqu'à ce que les lectures d'images et les transcriptions vidéo soient prêtes : inutile de mettre en pause.
  4. Charger le contexte client : get_conversation renvoie identityVerified, les verifiedTraits signés, ainsi que la page d'origine de la conversation et le contexte client. Lorsqu'elle comporte un contact.id, passez cet identifiant à list_conversations pour charger les conversations précédentes du client.
  5. Réveiller à la demande : utilisez un webhook filtré par source pour message.created afin de réveiller l'agent immédiatement, puis rattrapez votre retard avec sync. Le flux durable fonctionne indépendamment de la livraison des webhooks. Utilisez un identifiant couvrant tous les canaux pour créer le webhook et restreindre ses identifiants de source ; l'agent conserve son identifiant d'exécution limité à la source.

Catalogue d'outils

Chaque opération de l'API publique est disponible sous forme d'outil. La portée requise est indiquée à côté de chacun.

get_connection_info
Read connection access
conversations:read
get_conversation_context
Read support context
conversations:read
list_conversation_checks
Read conversation checks
conversations:read
record_conversation_check
Record a conversation check
conversations:write
get_status
Check Sonny status
conversations:read
create_conversation
Create a conversation from a form
conversations:write
upload_attachment
Upload a message attachment
attachments:write
list_properties
List custom properties
contacts:read
get_contact_properties
Read contact properties
contacts:read
set_contact_property
Set a contact property
contacts:write
list_contact_memories
Read customer memories
contact-memory:read
create_contact_memory
Save a customer memory
contact-memory:write
delete_contact_memory
Remove a customer memory
contact-memory:write
get_report
Read a support report
reporting:read
sync
Read workspace changes
conversations:read
batch_update_conversations
Update conversations in a batch
conversations:write
list_members
List members
members:read
list_teams
List teams
members:read
list_tags
List tags
tags:read
create_tag
Create a tag
tags:write
get_tag
Get a tag
tags:read
update_tag
Update a tag
tags:write
delete_tag
Delete a tag
tags:write
add_conversation_tag
Add a conversation tag
conversations:write
remove_conversation_tag
Remove a conversation tag
conversations:write
list_contacts
List contacts
contacts:read
create_contact
Create a contact
contacts:write
get_contact
Get a contact
contacts:read
update_contact
Update a contact
contacts:write
archive_contact
Archive a contact
contacts:write
erase_contact
Permanently erase a contact
contacts:write
list_channels
List conversation channels
conversations:read
list_sources
List sources
conversations:read
list_conversations
List conversations
conversations:read
get_conversation
Get a conversation
conversations:read
update_conversation
Update a conversation
conversations:write
list_messages
List messages
messages:read
create_internal_note
Create an internal note
messages:write
edit_message
Edit a sent reply
messages:send
send_message
Send a reply to the customer
messages:send
list_webhooks
List webhook endpoints
webhooks:read
create_webhook
Create a webhook endpoint
webhooks:write
list_webhook_events
List webhook event types
webhooks:read
update_webhook
Update a webhook endpoint
webhooks:write
delete_webhook
Delete a webhook endpoint
webhooks:write
test_webhook
Queue a test event
webhooks:write
list_webhook_deliveries
List webhook deliveries
webhooks:read
retry_webhook_delivery
Retry a failed delivery
webhooks:write
list_kb_articles
List knowledge base articles
kb:read
create_kb_article
Create a knowledge base article
kb:write
get_kb_article
Get a knowledge base article
kb:read
update_kb_article
Update a knowledge base article
kb:write
delete_kb_article
Delete a knowledge base article
kb:write
list_kb_categories
List knowledge base categories
kb:read
create_kb_category
Create a knowledge base category
kb:write
update_kb_category
Update a knowledge base category
kb:write
delete_kb_category
Delete a knowledge base category
kb:write
get_csat_summary
Get CSAT scores
csat:read
list_csat_ratings
List CSAT ratings
csat:read
get_conversation_csat
Get a conversation's CSAT rating
csat:read
reorder_kb_articles
Reorder knowledge base articles
kb:write
upsert_kb_article
Sync a knowledge base article
kb:write
reorder_kb_categories
Reorder knowledge base categories
kb:write
upsert_kb_category
Sync a knowledge base category
kb:write
get_kb_category
Get a knowledge base category
kb:read
get_help_center
Get help center settings
kb:read
update_help_center
Update help center settings
kb:write
upload_kb_media
Upload a help center image
kb:write
list_kb_audiences
List audiences
kb:read
create_kb_audience
Create audience
kb:write
update_kb_audience
Update audience
kb:write
delete_kb_audience
Delete audience
kb:write

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.

list_conversations({ status: "open", awaitingReply: true, compact: true, sort: "waitingSince", direction: "asc" })

Triez 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 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.

  1. Commencez sans curseur, suivez nextCursor jusqu'à ce que hasMore soit false, puis enregistrez ce curseur.
  2. Lisez les listes actuelles de conversations et de contacts, ainsi que l'historique nécessaire à votre état initial.
  3. 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 list_members / list_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.

batch_update_conversations({
  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.

set_contact_property({ contactId: "contact_1", propertyName: "Plan", value: "Pro" })
list_contacts({ property: { Plan: "Pro" } })

Les 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_report({ kind, filters }). 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. upload_attachment prend conversationId, fileName, contentType et dataBase64. 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.

send_message({ conversationId: "conversation_1", 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.

Explorer les contrats complets de requêtes et de réponses

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.

  1. Choisissez le sourceId de votre canal et accordez kb:read et kb:write. Pour la découverte optionnelle, list_sources nécessite aussi conversations:read.
  2. 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.
  3. 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.
Suivre le tutoriel complet de synchronisation MCP

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'aide

Documentation associée