Entwickler

Öffentliche API Beta

Baue Integrationen für deinen Arbeitsbereich mit sicheren API-Schlüsseln, eingeschränkten Berechtigungen und einem stabilen, versionierten JSON-Vertrag.

Interaktive API-Referenz öffnen

Schnellstart

  1. 01

    API-Schlüssel öffnen

    Öffne Einstellungen, wähle Entwickler, suche API-Schlüssel und wähle dann Schlüssel erstellen. Inhaber und Admins können Schlüssel erstellen.

  2. 02

    API-Schlüssel erstellen

    Gib unter Name einen Namen ein, wähle Läuft ab in (Tagen), setze Kanalzugriff auf Alle Kanäle oder Ausgewählte Kanäle und wähle unter Berechtigungen nur die Berechtigungen, die deine Integration mindestens braucht. Eine Anfrage gelingt nur, wenn der Schlüssel genau die Ressourcen-Aktion besitzt, die der Endpunkt verlangt. Wähle Schlüssel erstellen.

  3. 03

    API-Schlüssel speichern

    Der vollständige Schlüssel wird nur einmal angezeigt. Kopiere ihn in deinen Secret-Manager und wähle dann Ich habe ihn gespeichert.

  4. 04

    Schlüssel senden

    Verwende ein Bearer-Token oder sende denselben Wert in x-api-key. Schlüssel gehören niemals in Query-Strings oder Browser-Code.

cURL

curl https://www.usesonny.com/api/v1/contacts?limit=25 \
  --header "Authorization: Bearer sonny_your_key"

Schlüssel bleiben sicher

Schlüsselsicherheit
Schlüssel haben das Präfix sonny_, 64 zufällige Zeichen, werden nur als Einweg-Hash gespeichert, haben ein konfigurierbares Ablaufdatum und ein Limit von 600 Anfragen pro Minute je Schlüssel. Ein Schlüssel ist an genau einen Arbeitsbereich gebunden.
Um einen Schlüssel zu widerrufen, wähle den Papierkorb-Button daneben. Bestätige API-Schlüssel widerrufen? mit Löschen. Der Schlüssel funktioniert dann sofort nicht mehr.
Autorisierung bei jedem Aufruf
Sonny prüft Hash und Berechtigung und kontrolliert dann erneut die aktive Mitgliedschaft, Rolle und den Abrechnungsstatus der Person, die den Schlüssel erstellt hat. Wird diese Person entfernt oder deaktiviert, sind ihre Schlüssel sofort gesperrt.
Ausgewählte Kanäle gelten für jeden REST-API- und MCP-Aufruf. Endpunkte für Kontakte, Eigenschaften, Labels und die Webhook-Verwaltung erfordern Zugriff auf alle Kanäle. Formulare können mit contacts:write und conversations:write auf ausgewählten Kanälen Unterhaltungen erstellen; eigenständige Kontakt-Endpunkte gelten weiterhin für den ganzen Arbeitsbereich.

Berechtigungen

  • contacts:read
  • contacts:write
  • tags:read
  • tags:write
  • conversations:read
  • conversations:write
  • messages:read
  • messages:write
  • messages:send
  • webhooks:read
  • webhooks:write
  • kb:read
  • kb:write
  • csat:read
  • attachments:write
  • members:read
  • contact-memory:read
  • contact-memory:write
  • reporting:read

Ressourcen

Kontakte
Verwalte Kontakte, typisierte Eigenschaften, Filter auf exakte Werte und Kundengedächtnis. Archiviere einen Kontakt oder lösche ihn bei Datenschutzanfragen endgültig samt allen Unterhaltungen.
Quellen
Finde eingerichtete Quellen und ob sie Chat, E-Mail oder beides unterstützen.
Unterhaltungen
Erstelle Anfragen aus Formularen, filtere nach Handlungsbedarf, weise Agents oder Teams zu, stelle zurück, vergib Labels und aktualisiere im Stapel.
Sync
Spiele dauerhaft gespeicherte Änderungen und Löschvorgänge im Arbeitsbereich mit einem gespeicherten Cursor erneut ab.
Mitglieder und Teams
Finde zuweisbare Teammitglieder, ihre Verfügbarkeit und ihren tatsächlichen Kanalzugriff.
Berichte
Lies Berichte zu Support, Team, KI, Wissen, Leads und Verfügbarkeit.
Nachrichten
Lies den Nachrichtenverlauf und aus Anhängen extrahierte Inhalte, lade private Dateien hoch, füge interne Notizen hinzu und sende oder bearbeite Antworten an Kunden.
Webhooks
Verwalte Endpunkte, Abonnements, Tests, Zustellungen und Wiederholungen.
Wissensdatenbank
Erstelle, lies, aktualisiere und lösche Hilfecenter-Artikel und -Kategorien je Quelle.
Kundenzufriedenheit
Lies CSAT-Werte für den Arbeitsbereich, jeden Kanal und jede Unterhaltung und liste einzelne Bewertungen auf – gefiltert nach Bewertung, Kommentar, zuständiger Person oder Zeitraum.

Sonny aus einem KI-Tool nutzen

Sonny MCP stellt jede Operation der öffentlichen API als Tool bereit. Clients verbinden sich per Anmeldung mit OAuth 2.1 – oder mit einem API-Schlüssel mit eingeschränkten Berechtigungen –, und jeder Aufruf behält dieselben Berechtigungen, Arbeitsbereichsgrenzen und Geschäftsregeln.

Sonny-MCP-Leitfaden lesen

Antworten und Fehler

Antworten mit Sammlungen verwenden data und enthalten, wo sinnvoll, eine Paginierung. Jede Antwort enthält x-request-id; du kannst eine sichere Request-ID mitschicken, die Sonny dann zurückgibt. Fehler liefern eine sichere Meldung, ohne sensible Implementierungsdetails preiszugeben.

{
  "error": {
    "type": "validation_error",
    "message": "Invalid email address",
    "requestId": "req_01J..."
  }
}
400
Ungültige Eingabe, ungültiges JSON, ungültige Query oder ungültiger Cursor.
401
API-Schlüssel fehlt, ist ungültig, abgelaufen oder hat nicht die nötige Berechtigung.
402
Der Abrechnungsstatus des Arbeitsbereichs blockiert diese Anfrage.
403
Die Rolle der Person, die den Schlüssel erstellt hat, ist dafür nicht zugelassen.
404
Die Ressource existiert im Arbeitsbereich des Schlüssels nicht.
409
Die Anfrage steht im Konflikt mit einer bestehenden Ressource.
410
Sync-Cursor abgelaufen. Lade den aktuellen Stand neu und spiele ab einem neuen Cursor ab.
413
Der Upload überschreitet die erlaubte Größe.
422
Die Quelle hat keinen E-Mail-Kanal oder ein übermittelter Feldwert ist ungültig.
429
Das Rate-Limit pro Schlüssel wurde überschritten.
500
Ein unerwarteter Fehler ist aufgetreten. Versuche es mit der Request-ID erneut.
503
Der Rückstau bei der Webhook-Zustellung ist voll. Versuche es später erneut.

Rate-Limits

Jeder API-Schlüssel darf bis zu 600 Anfragen pro Minute stellen. Jede Antwort meldet das aktuelle Zeitfenster über die Standard-Header RateLimit-Limit, RateLimit-Remaining und RateLimit-Reset, damit Clients sich selbst drosseln können, statt zu raten. Wird das Limit überschritten, antwortet die API mit 429 und einem Retry-After-Header – warte so viele Sekunden, bevor du es erneut versuchst.

Versionierung und Abkündigung

Die API ist im URL-Pfad versioniert (/api/v1). Innerhalb einer Version machen wir nur ergänzende Änderungen – neue Endpunkte, neue optionale Felder, neue Enum-Werte. Inkompatible Änderungen erscheinen als neue Version, und bevor ein v1-Endpunkt eingestellt wird, kündigen wir das mindestens sechs Monate vorher an: auf dieser Seite, per E-Mail an Inhaber von Arbeitsbereichen mit aktiven API-Schlüsseln und über Deprecation- und Sunset-Header auf den betroffenen Endpunkten.

Gesendete Antwort bearbeiten

  1. Gib deinem API-Schlüssel oder deiner MCP-Verbindung die Berechtigungen messages:read und messages:send sowie Zugriff auf den Kanal der Antwort.
  2. Lies die Nachrichten der Unterhaltung und kopiere die ID einer Antwort, die du als Mensch gesendet hast. Ein API-Schlüssel handelt im Namen der Person, die ihn erstellt hat; OAuth im Namen des verbundenen Teammitglieds.
  3. Sende den neuen Text mit der Anfrage unten oder rufe in MCP edit_message mit conversationId, messageId und body auf.
  4. Prüfe die zurückgegebene Nachricht. ID, Anhänge, Lesebestätigung und ursprüngliche Sendezeit bleiben unverändert.
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"}'

Beim Bearbeiten werden der Verlauf und verbundene Chat-Clients korrigiert. Es wird keine weitere E-Mail oder Benachrichtigung gesendet, und bereits zugestellte E-Mails bleiben unverändert. Bearbeiten lassen sich nur deine eigenen, von Menschen verfassten Antworten an Kunden – eingehende Nachrichten, Bot-Antworten, interne Notizen und Antworten anderer Teammitglieder nicht. Warte, bis eine ausstehende E-Mail-Zustellung abgeschlossen ist, bevor du bearbeitest. Der neue Text muss 1–50.000 Zeichen lang sein; bisheriges HTML und Link-Vorschauen werden entfernt. Integrationen erhalten einen message.updated-Webhook und ein Sync-Ereignis. Wer nur nach neueren Nachrichten-IDs pollt, findet keine Bearbeitungen; nutze den dauerhaften Sync-Feed.

Unterhaltung aus einem Formular erstellen

Sende eine Formularübermittlung an POST /api/v1/conversations. Sonny findet oder erstellt den Kontakt anhand der E-Mail, speichert die Antworten und eröffnet eine eingehende Unterhaltung im E-Mail-Kanal der gewählten Quelle. Team, Zuweisungsregeln und Benachrichtigungen des Kanals greifen. Agents antworten per E-Mail.

  1. Erstelle einen Schlüssel mit conversations:write und contacts:write. Du kannst ihn auf die ausgewählten Kanäle des Kunden beschränken. Die Quellen-ID findest du mit GET /api/v1/sources, wofür zusätzlich conversations:read nötig ist.
  2. Füge in n8n einen HTTP Request-Node hinzu: Methode POST, URL https://www.usesonny.com/api/v1/conversations. Speichere den Schlüssel in einer Header-Auth-Credential: Authorization mit dem Wert Bearer sonny_your_key.
  3. Aktiviere Send Body, wähle JSON und Using JSON, stelle dann das gesamte JSON-Feld auf Expression um und füge dieses Beispiel ein. Ersetze die Quellen-ID und ordne die Eingabefelder deinem Formular zu. Verwende die stabile, eindeutige Übermittlungs-ID des Formulars, damit ein erneuter Versuch denselben Wert nutzt.
{{ {
  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
} }}

Weitere Node-Optionen findest du im n8n-Leitfaden zu HTTP Request. Das passende MCP-Tool ist create_conversation mit derselben Payload und denselben Berechtigungen.

Neue Feldnamen werden zu Text-Eigenschaften. Bestehende Zahlen-, URL-, Datums- und Auswahlfelder müssen gültige String-Werte erhalten; ein ungültiger Wert liefert 422 mit dem Namen des Felds, und nichts wird gespeichert. Datumsfelder akzeptieren ISO-Daten oder Zeitstempel; Auswahlwerte müssen einer Option entsprechen. Bis zu 50 Felder werden angenommen, mit Namen bis 100 Zeichen und Werten bis 5.000 Zeichen. Eigenschaften erscheinen beim Kontakt und in der Seitenleiste der Unterhaltung. Beide Nachrichtentexte enthalten eine Kopie der Antworten, auch wenn du das optionale htmlMessage mitschickst.

Das optionale tags akzeptiert bis zu 20 bestehende Label-IDs des Arbeitsbereichs. Die Antwort enthält conversation, eine contact-Zusammenfassung, message und deduplicated. Neue Übermittlungen liefern 201. Wird externalId auf derselben Quelle erneut verwendet, kommt 200 mit den ursprünglichen IDs und deduplicated: true zurück; geänderte Inhalte werden ignoriert. Ohne externe ID erstellt jeder Aufruf eine neue Unterhaltung. Anhänge beim Erstellen und KI-Autoantworten werden nicht unterstützt.

Agent-Workflows

Sichten, handeln und synchron bleiben

REST und MCP teilen dieselben Berechtigungen und Workflows. Zugangsdaten können deinen aktuellen Kanalzugriff nur einschränken; entfernst du einen Kanal aus deiner Mitgliedschaft, verschwindet er auch aus deinen Integrationen.

Unterhaltungen mit Handlungsbedarf finden

Filtere nach awaitingReply, unread, unassigned, assigneeId, agentGroupId, snoozed, priority oder tagIds. awaitingReply ignoriert interne Notizen; unread bezieht sich auf das authentifizierte Teammitglied. unassigned bedeutet: keine einzelne zuständige Person, auch wenn ein Team zugewiesen ist. Labels passen, wenn eine der angegebenen IDs zutrifft.

GET /api/v1/conversations?status=open&awaitingReply=true&compact=true&sort=waitingSince&direction=asc

Sortiere nach waitingSince, lastMessageAt, createdAt oder geschäftlicher Priorität mit der Richtung asc oder desc. Bei Gleichstand entscheidet die ID. Ohne Angabe gelten compact=false und snoozed=any. In REST akzeptiert tagIds kommagetrennte IDs; MCP akzeptiert auch ein Array. waitingSince beginnt mit der ersten eingehenden Nachricht nach der letzten Antwort; Nachfragen und interne Notizen setzen den Wert nicht zurück. Führe diesen Scan der Warteschlange regelmäßig aus, auch wenn kein Webhook eintrifft, damit alte Threads wieder auftauchen.

Aufholen, ohne den Posteingang neu zu lesen

Nutze GET /api/v1/sync mit conversations:read. Der dauerhafte Feed enthält Änderungen an Unterhaltungen, Labels, Nachrichten, Kontakteigenschaften, Gedächtnis-Einträgen sowie Löschvorgänge. Jede Payload braucht zusätzlich ihre eigene Lese-Berechtigung: Nachrichtentexte brauchen messages:read, Gedächtnis-Einträge contact-memory:read. Eingeschränkte Zugangsdaten erhalten nur erlaubte Kanäle.

  1. Starte ohne Cursor, folge nextCursor, bis hasMore false ist, und speichere diesen Cursor.
  2. Lies die aktuellen Unterhaltungs- und Kontaktlisten sowie den Verlauf, den du für deinen Ausgangszustand brauchst.
  3. Spiele ab dem gespeicherten Cursor erneut ab, um Änderungen während dieses Lesens aufzufangen. Verarbeite jede Seite und speichere dann nextCursor.

Dedupliziere anhand der Ereignis-id: Die Wiedergabe erfolgt mindestens einmal, nachgelagerte Aktionen brauchen also einen eigenen Duplikatschutz. Eine Anfrage ohne Cursor deckt die letzte Stunde ab, keinen vollständigen Snapshot. Ereignisse werden 30 Tage aufbewahrt; HTTP 410 resync_required heißt: neu initialisieren. Initialisiere auch neu, nachdem du Berechtigungen oder Kanalzugriff erweitert hast. Verwende limit bis 100 und maxBodyChars bis 10.000 (Standard 500). Setze compact=true für die Nachrichtenfelder textPreview/textTruncated mit maximal 200 Zeichen statt body/bodyTruncated. Webhooks können einen Agent wecken; der Feed bleibt auch ohne Webhook-Abonnements oder bei einem Rückstau in der Webhook-Zustellung verfügbar.

Prüfungen einmal festhalten und das Ergebnis teilen

Bevor du eine Untersuchung wiederholst, lies list_conversation_checks (GET /api/v1/conversations/{conversationId}/checks). Speichere ein Ergebnis mit record_conversation_check (PUT auf denselben Pfad) und gib key, result, checkedBy und optional eine reference für die Karten-ID oder URL an. Zum Beispiel: key=product-version, result=Shopstar Go verified, checkedBy=Engineer, reference=card-X. Sonny speichert die authentifizierte actorId und den Zeitstempel checkedAt. Wird ein key erneut verwendet, ersetzt das nur diese Prüfung; es ist der aktuelle Stand, kein Verlaufsprotokoll. Lesen braucht conversations:read, Schreiben conversations:write, beides beschränkt auf den Kanal der Unterhaltung. Diese Aufrufe senden keine Antwort und markieren die Anfrage nicht als beantwortet.

Arbeit im Stapel zuweisen und aktualisieren

Finde aktive, zuweisbare Teammitglieder und Teams mit GET /api/v1/members and /teams (members:read). Die Antworten enthalten Verfügbarkeit und tatsächlichen Kanalzugriff, aber keine E-Mail-Adressen. Mit conversations:write änderst du status, priority, assigneeId, agentGroupId, snoozedUntil, snoozedUntilReply, addTagIds oder removeTagIds.

POST /api/v1/conversations/batch
{
  "conversationIds": ["conversation_1", "conversation_2"],
  "updates": { "agentGroupId": "team_1", "assignment": "round_robin" }
}

Round-Robin wählt ein verfügbares Teammitglied, das Zugriff auf den Kanal der Unterhaltung hat. Gibt es kein passendes Mitglied, liefert eine einzelne Aktualisierung 409 und ein Stapel-Eintrag schlägt fehl. Jeder Stapel akzeptiert bis zu 100 eindeutige IDs und wendet pro Unterhaltung einen Patch atomar an. Prüfe jedes { id, ok, error? }-Ergebnis; einzelne Einträge können fehlschlagen. Stapel unterliegen dem normalen anfragebasierten Rate-Limit, ohne Gewichtung nach Anzahl der Einträge.

Kundenkontext mit Sonny AI teilen

Liste, speichere und entferne Gedächtnis-Einträge zu Kontakten mit contact-memory:read/write. Gib sowohl contactId als auch eine zugängliche sourceId an; der Kontakt muss auf dieser Quelle eine Unterhaltung haben. Gespeicherte Fakten durchlaufen dieselbe Validierung, Duplikatbehandlung und dieselben Limits wie in der App und werden als manuelle Gedächtnis-Einträge gespeichert.

Lies Eigenschaftsdefinitionen unter /api/v1/properties und lies oder setze Werte unter /api/v1/contacts/{contactId}/properties. MCP stellt list_properties, get_contact_properties und set_contact_property bereit. Dafür sind contacts:read/write und Zugriff auf alle Kanäle nötig. Gib genau eine propertyId oder einen propertyName an, mit einem String-Wert oder null zum Leeren. Text-, Zahlen-, URL-, Datums- und Auswahlwerte werden gegen die Felddefinition geprüft.

PUT /api/v1/contacts/contact_1/properties
{ "propertyName": "Plan", "value": "Pro" }

GET /api/v1/contacts?property[Plan]=Pro

Eigenschaftsfilter vergleichen exakt gespeicherte Strings; mehrere Eigenschaften müssen alle zutreffen. Per API geschriebene Werte sind im Co-Pilot und im Autoresponder als API-Daten gekennzeichnet. Bestehende Regeln für verifizierte Kunden und Quellen gelten weiterhin. Normale, manuell gepflegte interne Feldwerte bleiben aus diesem KI-Kontext ausgeschlossen.

Dieselben Berichte lesen wie dein Team

Rufe mit reporting:read GET /api/v1/reporting/{kind} auf. Verfügbare Arten sind overview, volume, response-times, agents, sources, tags, csat, ai, knowledge, leads und online-hours. overview kombiniert Anzahlen, Antwortzeiten und CSAT. Filter sind period (1–365 Tage, Standard 30), from/to als Paar (to ist exklusiv), granularity (day/month), source, assigneeId und tagId. source akzeptiert all, all-chat, all-email, website:{id} oder email:{id}.

Berichte nutzen dieselben Abfragen wie das Dashboard und die aktuellen Zugriffsprüfungen. knowledge berücksichtigt Datum und erlaubte Kanäle, unabhängig von gewählter Quelle, zuständiger Person oder Label. online-hours misst die Anwesenheit zugänglicher Teammitglieder im Arbeitsbereich; die Anzahl der Unterhaltungen bleibt auf Kanäle beschränkt. Die bestehenden /csat-Endpunkte behalten ihre eigene Berechtigung csat:read und können eine andere Grundgesamtheit beschreiben.

Dateien mit Antworten oder internen Notizen senden

Erteile attachments:write und lade für eine Unterhaltung eine Datei bis 25 MB hoch. POST /api/v1/attachments erwartet die Multipart-Felder file und conversationId. Die Antwort enthält eine id und expiresAt. Übergib innerhalb einer Stunde bis zu 10 attachmentIds an eine Antwort oder Notiz. Jeder Upload ist an deinen Benutzer und die Unterhaltung gebunden und kann nur einmal verwendet werden. Ungenutzte Uploads werden nach Ablauf entfernt.

POST /api/v1/conversations/conversation_1/reply
{ "attachmentIds": ["upload_1"] }

Antworten erfordern messages:send; interne Notizen erfordern messages:write und erreichen niemals Kunden. Nachrichten nur mit Anhängen werden unterstützt. E-Mail-Antworten enthalten Dateien bis zur E-Mail-Größengrenze und Download-Links für den Rest; Offline-Chat-E-Mails enthalten Datei-Links. Links in E-Mails bleiben nutzbar, solange der Anhang existiert, sodass Empfänger sie auch später öffnen können. Wer die E-Mail weiterleitet, teilt den Zugriff auf diese Dateien. Prüfe emailDeliveryStatus auf Zustellfehler.

Autorisierte Nachrichten-Abrufe enthalten downloadUrl, downloadExpiresAt, aiStatus, aiDescription und aiExtractedText sowie videoTranscripts für verlinkte Videos (Loom, Vimeo und andere). Download-Links gelten 15 Minuten; lies die Nachricht erneut für frische Links. Neue Uploads über API/MCP werden privat gespeichert. Ältere Anhänge bleiben öffentlich und sind mit access=legacy_public gekennzeichnet: Ihre ursprüngliche URL läuft nicht ab. Das Lesen einer Nachricht startet die Bildauswertung, wenn der Arbeitsbereich Sonny AI hat. Bildauswertungen und Video-Transkripte sind kurz nach Eingang einer Nachricht fertig: Solange noch welche laufen, beginnt die Antwort mit readsInProgress, dessen nextStep den genauen nächsten Aufruf angibt. Übergib waitSeconds (bis 30), um in einer einzigen Anfrage darauf zu warten. Kundenseitige Widget- und Echtzeit-Nachrichten enthalten nie Extraktionen oder Transkripte.

Vollständige Request- und Response-Verträge ansehen

Wissensdatenbank

Aus einer externen Quelle synchronisieren

Synchronisiere Artikel und Kategorien über stabile externe IDs, importiere Markdown oder HTML, lade Bilder hoch, lege die Reihenfolge fest und verwalte Leser-Zielgruppen. Ein wiederholtes Upsert aktualisiert die vorhandenen Inhalte.

  1. Wähle die sourceId deines Kanals und erteile kb:read und kb:write. Bewahre den API-Schlüssel auf deinem Server auf und beschränke seinen Kanalzugriff.
  2. Erstelle die Kategorie und synchronisiere dann einen Artikel als Entwurf. Prüfe Formatierung und Zugriff, bevor du veröffentlichst.
  3. Richte den Zugriff auf das Hilfecenter ein, veröffentliche und teste die Leseransicht. Nutze Paginierung und stabile externe IDs für spätere Aktualisierungen.
Vollständige REST-Sync-Anleitung ansehen

Kunden-Zielgruppen verwalten

Erstelle Gruppen aus verifizierten Kundenmerkmalen und wende sie auf ein Hilfecenter, eine Kategorie oder einen Artikel an. Alle geerbten Einschränkungen müssen zutreffen. API- und MCP-Zugangsdaten handeln innerhalb ihrer Berechtigungen als Mitarbeitende; nutze die Vorschau und teste eine echte Kundensitzung, um den Leserzugriff zu prüfen.

Hilfecenter-Zielgruppen einrichten und testen

Verwandte Anleitungen