Ontwikkelaars

Sonny MCP Beta

Koppel MCP-compatibele AI-assistenten — Claude, en elke client die het Model Context Protocol spreekt — aan je werkruimte, met dezelfde rechten en grenzen als de openbare API.

Lees de handleiding voor de openbare API

Snel aan de slag

  1. 01

    Voeg Sonny toe aan Claude

    Voeg in Claude of Cowork een aangepaste connector toe met de URL https://www.usesonny.com/api/mcp. Sonny ondersteunt automatische clientregistratie, dus je hoeft geen client-ID of secret te kopiëren.

  2. 02

    Geef toegang tot je werkruimte

    Claude opent Sonny in je browser. Log in, bekijk de gevraagde rechten en kies de werkruimte die je wilt koppelen. OAuth 2.1 met PKCE houdt de toegangs- en vernieuwingstokens beperkt tot precies die toestemming.

  3. 03

    Vraag je assistent om Sonny te gebruiken

    Tools beschrijven zichzelf, dus een prompt als “Toon mijn open gesprekken” is genoeg. Assistenten zien welke tools alleen lezen en welke iets wijzigen of verwijderen, dus een goede client vraagt eerst toestemming voordat hij iets aanpast.

Claude Code

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

JSON-clientconfiguratie

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

Werken met een API-sleutel

Kan een client OAuth niet afronden? Maak dan een API-sleutel met beperkte rechten aan via Instellingen → Ontwikkelaar en stuur die mee als Authorization Bearer-header. API-sleutels blijven volledig ondersteund voor server-naar-server-koppelingen en oudere clients.

"Authorization": "Bearer sonny_your_key"

Zo houdt Sonny toolaanroepen veilig

Eén werkruimte, gekozen rechten
Elke aanroep draait binnen de werkruimte die je bij de OAuth-toestemming koos, of binnen de werkruimte waar de API-sleutel bij hoort. Een tool werkt alleen als de inloggegevens het vereiste recht hebben.
Eerlijke toolannotaties
Tools die alleen lezen zijn als alleen-lezen gemarkeerd; tools die iets bijwerken of verwijderen zijn als destructief gemarkeerd, zodat je client eerst om bevestiging kan vragen.
Dezelfde bedrijfsregels
Tools voeren exact dezelfde workflows uit als de openbare API — auditgeschiedenis, meldingen en webhooks werken allemaal alsof een teamlid de wijziging heeft gedaan.

Houd een assistent binnen één inbox

Geselecteerde kanalen op een API-sleutel worden automatisch afgedwongen bij elke toolaanroep. API-sleutels en OAuth-koppelingen volgen bovendien de huidige kanaaltoegang van het gekoppelde teamlid. Bij OAuth-koppelingen of sleutels met toegang tot alle kanalen bevat een werkruimte vaak meerdere bronnen — één per product of merk. Laat je assistent één keer list_sources aanroepen om ze te vinden en daarna sourceId meegeven aan list_conversations, zodat vragen over één product alleen de gesprekken van dat product opleveren. Elk gesprek heeft ook een eigen sourceId, dus je kunt de resultaten controleren.

Draai een goedkope supportloop

  1. Wijzigingen ontdekken: begin met de duurzame sync-feed, sla nextCursor op nadat je elke pagina hebt verwerkt en ontdubbel event-ID's. Om werk te kiezen roep je list_conversations aan met sourceId, awaitingReply: true, snoozed: "false" en compact: true. Interne notities verbergen geen onbeantwoorde klantberichten.
  2. Lees alleen nieuwe tekst: roep voor elk gewijzigd gesprek list_messages aan met je laatste bericht-ID of ISO-tijdstempel in after en zet includeHtml: false, tenzij je de HTML van de e-mail echt nodig hebt.
  3. Wacht op afbeeldingen en video's: als list_messages readsInProgress teruggeeft, doe dan de aanroep uit de bijbehorende nextStep. Met waitSeconds wacht de response tot het lezen van afbeeldingen en de videotranscripten klaar zijn, dus je hoeft zelf niet te wachten.
  4. Laad klantcontext: get_conversation geeft identityVerified, ondertekende verifiedTraits en de herkomstpagina en clientcontext van het gesprek terug. Heeft het een contact.id? Geef die ID dan mee aan list_conversations om eerdere gesprekken van de klant te laden.
  5. Wakker worden wanneer nodig: gebruik een op bron gefilterde webhook voor message.created om de agent direct te wekken en haal daarna de rest in met sync. De duurzame feed werkt los van de webhookaflevering. Gebruik inloggegevens met toegang tot alle kanalen om de webhook in te stellen en de bron-ID's te beperken; de agent houdt zijn eigen, tot de bron beperkte runtime-inloggegevens.

Toolcatalogus

Elke bewerking van de openbare API is beschikbaar als tool. Het vereiste recht staat bij elke tool vermeld.

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

Agent-workflows

Triëren, handelen en gesynchroniseerd blijven

REST en MCP delen dezelfde rechten en workflows. Inloggegevens kunnen je huidige kanaaltoegang alleen verder beperken; haal je een kanaal uit je lidmaatschap, dan verdwijnt het ook uit je integraties.

Gesprekken vinden die aandacht nodig hebben

Filter op awaitingReply, unread, unassigned, assigneeId, agentGroupId, snoozed, priority of tagIds. Wacht op antwoord negeert interne notities; ongelezen geldt specifiek voor het ingelogde teamlid. Niet toegewezen betekent geen individuele toegewezen persoon, ook als er wel een team is toegewezen. Labels matchen op elke opgegeven ID.

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

Sorteer op waitingSince, lastMessageAt, createdAt of zakelijke prioriteit, met direction asc of desc. ID's beslissen bij gelijke waarden. Weggelaten filters houden compact=false en snoozed=any aan. REST-tagIds accepteert ID's gescheiden door komma's; MCP accepteert ook een array. waitingSince begint bij het eerste inkomende bericht na het laatste antwoord; vervolgberichten en interne notities resetten het niet. Laat deze scan van de wachtrij volgens een schema draaien, ook als er geen webhook binnenkomt, zodat oude threads weer bovenkomen.

Bijblijven zonder de inbox opnieuw te lezen

Gebruik sync met conversations:read. De duurzame feed bevat gesprekswijzigingen, labels, berichten, contacteigenschappen, geheugen en verwijderrecords. Elke payload vereist ook een eigen leesrecht: berichtteksten hebben messages:read nodig en geheugen heeft contact-memory:read nodig. Beperkte inloggegevens ontvangen alleen toegestane kanalen.

  1. Begin zonder cursor, volg nextCursor tot hasMore false is en sla die cursor op.
  2. Lees de huidige lijsten met gesprekken en contacten en de geschiedenis die je nodig hebt voor je beginstand.
  3. Speel af vanaf de opgeslagen cursor om wijzigingen tijdens dat lezen op te vangen. Verwerk elke pagina en sla daarna nextCursor op.

Ontdubbel op event-id: het afspelen gebeurt minstens één keer, dus acties verderop hebben hun eigen bescherming tegen dubbele verwerking nodig. Een request zonder cursor beslaat het laatste uur, geen volledige momentopname. Events worden 30 dagen bewaard; HTTP 410 resync_required betekent dat je opnieuw moet beginnen. Begin ook opnieuw na het verruimen van rechten of kanaaltoegang. Gebruik limit tot 100 en maxBodyChars tot 10.000 (standaard 500). Zet compact=true voor de berichtvelden textPreview/textTruncated, begrensd op 200 tekens, in plaats van body/bodyTruncated. Webhooks kunnen een agent wekken; de feed blijft beschikbaar zonder webhookabonnementen of als de webhookaflevering achterloopt.

Controles één keer vastleggen en het resultaat delen

Lees list_conversation_checks (GET /api/v1/conversations/{conversationId}/checks) voordat je een onderzoek herhaalt. Sla een resultaat op met record_conversation_check (PUT naar hetzelfde pad), met key, result, checkedBy en een optionele reference voor de kaart-ID of URL. Bijvoorbeeld: key=product-version, result=Shopstar Go verified, checkedBy=Engineer, reference=card-X. Sonny legt de ingelogde actorId en het tijdstempel checkedAt vast. Hergebruik je een key, dan wordt alleen die controle vervangen; dit is de huidige stand, geen geschiedenislog. Lezen vereist conversations:read en schrijven conversations:write, allebei beperkt tot het kanaal van het gesprek. Deze aanroepen versturen geen antwoord en markeren het gesprek niet als beantwoord.

Werk in bulk toewijzen en bijwerken

Vind actieve teamleden en teams aan wie je kunt toewijzen met list_members / list_teams (members:read). Responses bevatten beschikbaarheid en daadwerkelijke kanaaltoegang, zonder e-mailadressen. Gebruik conversations:write om status, priority, assigneeId, agentGroupId, snoozedUntil, snoozedUntilReply, addTagIds of removeTagIds te wijzigen.

batch_update_conversations({
  conversationIds: ["conversation_1", "conversation_2"],
  updates: { agentGroupId: "team_1", assignment: "round_robin" }
})

Round-robin kiest een beschikbaar teamlid dat toegang heeft tot het kanaal van het gesprek. Is er niemand geschikt, dan geeft een losse update 409 terug en mislukt een item in de bulkactie. Elke bulkactie accepteert maximaal 100 unieke ID's en past per gesprek één patch atomair toe. Controleer elk { id, ok, error? }-resultaat; sommige items kunnen mislukken. Bulkacties vallen onder de huidige limiet per request, zonder extra gewicht per aantal items.

Klantcontext delen met Sonny AI

Toon, bewaar en verwijder contactgeheugen met contact-memory:read/write. Geef zowel contactId als een toegankelijke sourceId mee; het contact moet een gesprek op die bron hebben. Opgeslagen feiten gebruiken dezelfde validatie, verwerking van dubbelingen en limieten als de app en worden vastgelegd als handmatig geheugen.

Lees eigenschapsdefinities via /api/v1/properties en lees of stel waarden in via /api/v1/contacts/{contactId}/properties. MCP biedt list_properties, get_contact_properties en set_contact_property. Hiervoor zijn contacts:read/write en toegang tot alle kanalen nodig. Geef precies één propertyId of propertyName op, met een tekstwaarde of null om hem te wissen. Waarden voor tekst, getal, URL, datum en keuze worden gevalideerd tegen de velddefinitie.

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

Eigenschapsfilters matchen op exact opgeslagen tekst; bij meerdere eigenschappen moeten ze allemaal overeenkomen. Waarden die via de API zijn ingesteld, worden in AI Copilot en de autoresponder gelabeld als API-gegevens. Bestaande regels voor geverifieerde klanten en bronnen blijven gelden. Gewone handmatige interne veldwaarden blijven buiten deze AI-context.

Dezelfde rapporten lezen als je team

Roep met reporting:read get_report({ kind, filters }) aan. De soorten zijn overview, volume, response-times, agents, sources, tags, csat, ai, knowledge, leads en online-hours. Overview combineert aantallen, reactietijden en CSAT. Filters zijn period (1–365 dagen, standaard 30), from/to als paar (to telt niet mee), granularity (day/month), source, assigneeId en tagId. Source accepteert all, all-chat, all-email, website:{id} of email:{id}.

Rapporten gebruiken dezelfde queries als het dashboard en de huidige toegangscontroles. Knowledge gebruikt datums en toegestane kanalen, los van de gekozen bron, toegewezen persoon of label. Online-hours meet de aanwezigheid van toegankelijke teamleden in de werkruimte; de gespreksaantallen daarin blijven beperkt tot kanalen. De bestaande /csat-endpoints houden hun eigen recht csat:read en kunnen een andere groep beschrijven.

Bestanden meesturen met antwoorden of interne notities

Geef attachments:write en upload een bestand van maximaal 25 MB voor een gesprek. upload_attachment gebruikt conversationId, fileName, contentType en dataBase64. De response bevat een id en expiresAt. Geef binnen een uur maximaal 10 attachmentIds mee aan een antwoord of notitie. Elke upload is gekoppeld aan jouw gebruiker en gesprek en kan maar één keer worden gebruikt. Ongebruikte uploads worden na het verlopen opgeruimd.

send_message({ conversationId: "conversation_1", attachmentIds: ["upload_1"] })

Antwoorden vereisen messages:send; interne notities vereisen messages:write en bereiken klanten nooit. Berichten met alleen bijlagen worden ondersteund. E-mailantwoorden bevatten bestanden binnen de maximale e-mailgrootte en downloadlinks voor de rest; offline chatmails bevatten links naar bestanden. Gemailde links blijven bruikbaar zolang de bijlage bestaat, zodat ontvangers ze later kunnen openen. Wie de e-mail doorstuurt, deelt ook toegang tot die bestanden. Controleer emailDeliveryStatus op mislukte afleveringen.

Geautoriseerde berichten bevatten downloadUrl, downloadExpiresAt, aiStatus, aiDescription en aiExtractedText, plus videoTranscripts voor gelinkte video's (Loom, Vimeo en andere). Downloadlinks zijn 15 minuten geldig; lees het bericht opnieuw voor verse links. Nieuwe uploads via API/MCP worden privé opgeslagen. Oudere bijlagen blijven openbaar en zijn gemarkeerd met access=legacy_public: hun oorspronkelijke URL verloopt niet. Het lezen van een bericht start het lezen van de afbeeldingen als de werkruimte Sonny AI heeft. Het lezen van afbeeldingen en videotranscripten is kort na binnenkomst van een bericht klaar: zolang er nog iets loopt, begint de response met readsInProgress, waarvan nextStep precies aangeeft welke aanroep je moet doen. Geef waitSeconds (maximaal 30) mee om er in één request op te wachten. Widget- en realtimeberichten voor klanten bevatten nooit uitgelezen inhoud of transcripten.

Bekijk de volledige request- en responsecontracten

Kennisbank

Synchroniseren vanuit een externe bron

Synchroniseer artikelen en categorieën met vaste externe ID's, importeer Markdown of HTML, upload afbeeldingen, stel de volgorde in en beheer lezersdoelgroepen. Een upsert herhalen werkt de bestaande inhoud bij.

  1. Kies de sourceId van je kanaal en geef kb:read en kb:write. Voor optionele ontdekking heeft list_sources ook conversations:read nodig.
  2. Maak de categorie aan en synchroniseer daarna een artikel als concept. Controleer de opmaak en toegang voordat je publiceert.
  3. Stel de toegang tot het helpcentrum in, publiceer en test de lezersweergave. Gebruik paginering en vaste externe ID's voor latere updates.
Volg de volledige stapsgewijze uitleg voor synchroniseren via MCP

Klantdoelgroepen beheren

Maak groepen op basis van geverifieerde klantkenmerken en pas ze toe op een helpcentrum, categorie of artikel. Alle overgenomen beperkingen moeten overeenkomen. API- en MCP-inloggegevens handelen als medewerker binnen hun rechten; bekijk een voorbeeld en test met een echte klantsessie om de lezerstoegang te controleren.

Doelgroepen voor het helpcentrum instellen en testen

Gerelateerde handleidingen