Zum Inhalt springen
Dokumentation

REST-API

Chatte mit deinen intoCHAT-Agenten, lies ihre Gespräche, Leads und Wissensquellen, halte ihre Kontakte synchron und abonniere Webhooks, von deinem eigenen Server oder einem Automatisierungstool aus: API-Schlüssel, Scopes, Ratenlimits, Fehler, Paginierung und alle Endpunkte mit Beispielen.

Über die REST-API spricht dein eigener Server mit deinen Agenten. Sende eine Nachricht und bekomm die Antwort des Agenten, lies Gespräche und Leads, lege Kontakte an und aktualisiere sie, füge Wissensquellen hinzu oder entferne sie, und abonniere Webhooks für die Events eines Agenten, mit JSON über HTTPS. Die Apps für Zapier und Make bauen darauf auf. Eine Antwort über die API entsteht mit demselben Code wie eine Antwort im Chat-Widget, aus demselben Wissen und mit denselben Einstellungen.

Die API ist für Server gedacht. Sie sendet keine CORS-Header, eine Webseite auf einer anderen Website kann sie also nicht aufrufen, und dein API-Schlüssel darf nie in einem Browser oder in deinem Embed-Code auftauchen. Um einen Chat auf deiner Website zu zeigen, nutze das Script-Tag. Um Ereignisse zugeschickt zu bekommen, sobald sie passieren, nutze Webhooks.

Welche Pläne die API enthalten

Die API ist in Starter, Pro und Enterprise enthalten. Im Plan Free kannst du keine Schlüssel erstellen.

Wechselt ein Konto zurück zu Free, bleiben seine Schlüssel in der Liste, aber jede Anfrage bekommt einen Fehler 403 mit dem Code plan_required. Sie funktionieren wieder, sobald das Konto im Plan Starter oder höher ist.

Jede Antwort, die ein Agent über die API schreibt, zählt als eine Nachricht deines Plans, genau wie eine Antwort im Widget, und zählt auf das monatliche Nachrichtenlimit des Agenten, falls du eines festgelegt hast. Daten lesen sowie Quellen hinzufügen oder löschen verbraucht keine Nachrichten. Siehe Was als Nachricht zählt.

API-Schlüssel erstellen

  1. Klicke in der Seitenleiste unter Settings auf API keys.
  2. Gib dem Schlüssel unter Create a key einen Name, an dem du ihn später wiedererkennst, zum Beispiel CRM sync.
  3. Lass unter Access die Option Every scope, including ones added later gewählt, oder wähle Only the scopes I choose und hake die Scopes an, die dieser Schlüssel braucht. Siehe Scopes.
  4. Klicke auf Create key.
  5. Klicke auf Copy, leg den Schlüssel dort ab, wo dein Server ihn lesen kann, zum Beispiel in einer Umgebungsvariablen, und klicke auf I've saved it.

Ein Schlüssel besteht aus ic_live_, gefolgt von 32 Buchstaben und Ziffern. Er wird nur einmal angezeigt: intoCHAT speichert nur einen Fingerabdruck davon, niemand kann ihn dir also erneut anzeigen. Hast du ihn verloren, widerrufe ihn und erstelle einen neuen.

Ein Schlüssel gehört zum Konto, nicht zu der Person, die ihn erstellt hat. Er funktioniert im Rahmen seiner Scopes für jeden Agenten im Konto und funktioniert weiter, wenn diese Person das Team verlässt. Ein Konto kann bis zu 20 aktive Schlüssel haben.

Nur der Owner des Kontos und Admins können Schlüssel erstellen und widerrufen. Editoren und Viewer sehen die Liste der Schlüssel, nur mit deren ersten Zeichen. Siehe Teammitglieder und Rollen.

Die Schlüsselliste

Jeder Schlüssel zeigt seinen Namen, seine ersten Zeichen (zum Beispiel ic_live_3f9A…), seine Scopes, wann er erstellt und wann er zuletzt benutzt wurde. Last used wird höchstens einmal pro Minute aktualisiert.

Schlüssel widerrufen

Klicke neben dem Schlüssel auf Revoke und bestätige. Der Schlüssel funktioniert ab seiner nächsten Anfrage nicht mehr, und das lässt sich nicht rückgängig machen. Widerrufe einen Schlüssel, sobald du glaubst, dass jemand anderes ihn haben könnte.

Widerrufst du einen Schlüssel, werden auch die Webhooks gelöscht, die er abonniert hat, etwa für Zapier oder Make, samt Zustellverlauf: Sonst könnte sie nichts mehr entfernen. Webhooks, die du im Tab Leads hinzugefügt hast, sind nicht betroffen.

Authentifizierung

Sende den Schlüssel bei jeder Anfrage im Header Authorization:

curl https://www.intochat.ai/api/v1/agents \
  -H "Authorization: Bearer ic_live_YOUR_KEY"

Alle Endpunkte liegen unter https://www.intochat.ai/api/v1. Anfragen mit Body senden JSON mit Content-Type: application/json, und jede Antwort ist JSON, außer einer gestreamten Chat-Antwort. Die API nutzt keine Cookies und keine Login-Sitzung: Allein der Schlüssel entscheidet, was eine Anfrage darf.

Ein fehlender, fehlerhafter, unbekannter oder widerrufener Schlüssel bekommt einen Fehler 401 mit dem Code unauthorized.

Scopes

Ein Scope erlaubt einem Schlüssel, eine Gruppe von Endpunkten zu nutzen. Ein Schlüssel, der mit Every scope, including ones added later erstellt wurde, kann jeden Endpunkt nutzen, auch künftig hinzukommende.

ScopeErlaubt
agents:readAgenten auflisten und einen Agenten abrufen
chatEine Nachricht an einen Agenten senden. Jede Antwort zählt als Nachricht deines Plans.
conversations:readGespräche auflisten und ein Gespräch mit Verlauf abrufen
leads:readLeads auflisten, Kontakte auflisten und einen Kontakt abrufen sowie die Lead-, Formular-, Buchungs- und Rücksende-Events von Events auflisten und Beispiel-Events abrufen
contacts:writeEinen Kontakt anlegen oder aktualisieren, einen Kontakt ändern und einen Kontakt löschen
sources:readQuellen auflisten
sources:writeEine Quelle hinzufügen und eine Quelle löschen, was auch das Training startet
webhooks:writeEinen Webhook abonnieren und einen Webhook abbestellen

conversations:read deckt außerdem die Übergabe-, Live-Chat- und Neues-Gespräch-Events von Events auflisten ab.

Eine Anfrage an einen Endpunkt, für den der Schlüssel keinen Scope hat, bekommt einen Fehler 403 mit dem Code insufficient_scope. Um die Scopes eines Schlüssels zu ändern, erstelle einen neuen Schlüssel und widerrufe den alten.

Ratenlimits

Jeder Schlüssel kann 60 Anfragen pro Minute stellen, über alle Endpunkte zusammen. Jede Antwort, die die Schlüsselprüfung bestanden hat, trägt diese Header:

HeaderWert
X-RateLimit-Limit60
X-RateLimit-RemainingVerbleibende Anfragen in der aktuellen Minute
X-RateLimit-ResetWann die Minute endet, in Unix-Sekunden

Über dem Limit bekommt die Anfrage einen Fehler 429 mit dem Code rate_limited und einen Header Retry-After mit den Sekunden, die du warten musst.

Für den Chat gelten zwei weitere Limits, die nicht vom Schlüssel abhängen: die Nachrichten deines Plans, und ein Agent beantwortet höchstens 1.000 Nachrichten pro Stunde, Widget und API zusammen. Darüber bekommt eine Chat-Anfrage einen Fehler 429 mit dem Code agent_busy.

Fehler

Jeder Fehler hat dieselbe Form:

{
  "error": {
    "code": "insufficient_scope",
    "message": "This API key doesn't have the \"chat\" scope."
  }
}

Werte in deinem Code code aus; message erklärt den Fehler für Menschen und kann sich ändern.

StatusCodeBedeutung
400invalid_requestDer Anfrage fehlt etwas, oder sie hat einen falschen Wert. Die Meldung sagt, welchen.
401unauthorizedKein Schlüssel, oder der Schlüssel ist fehlerhaft, unbekannt oder widerrufen.
403insufficient_scopeDem Schlüssel fehlt der Scope, den dieser Endpunkt braucht.
403plan_requiredDas Konto ist im Plan Free. Die API ist ab Starter enthalten.
403message_limit_reachedDas Konto hat in diesem Zeitraum alle Nachrichten seines Plans verbraucht.
403agent_cap_reachedDer Agent hat das monatliche Nachrichtenlimit erreicht, das unter Share, Limits and access festgelegt ist.
403agent_privateDer Agent ist privat und antwortet daher nur im Dashboard. Siehe Private Agenten.
403character_limit_exceededEine neue Quelle würde den Agenten über die Trainingszeichen seines Plans bringen.
403contact_limit_reachedEin neuer Kontakt würde den Agenten über die Kontakte pro Agent seines Plans bringen.
404not_foundDiesen Agenten, dieses Gespräch, diese Quelle, diesen Kontakt oder diesen Webhook gibt es in diesem Konto nicht.
409conflictEin anderer Kontakt des Agenten hat diese External ID oder E-Mail-Adresse schon.
429rate_limitedDer Schlüssel hat in dieser Minute mehr als 60 Anfragen gestellt.
429agent_busyDer Agent beantwortet gerade zu viele Nachrichten.
500internal_errorAuf unserer Seite ist etwas schiefgelaufen. Versuch es erneut.
504timeoutDer Agent hat zu lange für die Antwort gebraucht.

Ein Agent, ein Gespräch oder eine Quelle aus einem anderen Konto bekommt 404, genau wie etwas, das es nicht gibt.

Paginierung

Gespräche auflisten und Leads auflisten liefern jeweils eine Seite, die neuesten zuerst. Sie nehmen diese Query-Parameter an:

ParameterInhalt
limitEinträge pro Seite, von 1 bis 100. Standard ist 20.
cursorDer nextCursor der vorherigen Seite, um die nächste zu holen.
sinceEine ISO-8601-Zeit, zum Beispiel 2026-10-01T00:00:00Z. Es kommen nur Einträge mit Aktivität zu oder nach diesem Zeitpunkt: ein Gespräch mit einer Nachricht seitdem oder ein Lead, der seitdem gespeichert oder erneut abgeschickt wurde.

Eine Seite sieht so aus:

{
  "data": [ ],
  "hasMore": true,
  "nextCursor": "MjAyNi0xMC0wNFQwOTowMDowMC4wMDBafGNsdjEyMw"
}

Frag die nächste Seite mit ?cursor= und diesem Wert ab, mit demselben limit und since, bis hasMore den Wert false hat und nextCursor den Wert null. Die Reihenfolge richtet sich fest nach dem Erstellungszeitpunkt, neue Aktivität während des Blätterns lässt also keinen Eintrag doppelt erscheinen oder fehlen. Für eine regelmäßige Synchronisierung speichere den Zeitpunkt, zu dem die letzte begonnen hat, und übergib ihn beim nächsten Mal als since.

Agenten auflisten

GET /api/v1/agents · Scope agents:read

Alle Agenten im Konto, die neuesten zuerst.

curl https://www.intochat.ai/api/v1/agents \
  -H "Authorization: Bearer ic_live_YOUR_KEY"
{
  "data": [
    {
      "id": "AGENT_ID",
      "name": "Acme Assistant",
      "private": false,
      "status": "trained",
      "trainedAt": "2026-10-02T09:00:00.000Z",
      "characters": 48210,
      "counts": { "conversations": 312, "messages": 2240, "leads": 41, "sources": 18 },
      "createdAt": "2026-09-01T09:00:00.000Z",
      "updatedAt": "2026-10-02T09:00:00.000Z"
    }
  ]
}

status ist untrained, training, trained oder error (das letzte Training ist fehlgeschlagen). characters gibt an, wie viele Trainingszeichen die trainierten Quellen des Agenten belegen.

Agent abrufen

GET /api/v1/agents/{agentId} · Scope agents:read

Ein Agent in data, mit denselben Feldern wie unter Agenten auflisten.

Nachricht senden

POST /api/v1/agents/{agentId}/chat · Scope chat

Sendet eine Nachricht an den Agenten und liefert seine Antwort. Der Agent antwortet wie im Widget: aus seinem Wissen und seinen Anweisungen, mit deinen API-Aktionen, eigenen Buttons, Chat-Formularen, der Terminbuchung, der Übergabe per E-Mail und dem Live-Chat, soweit du sie eingerichtet hast.

FeldInhalt
messagePflicht. Der Text, bis zu 10.000 Zeichen.
conversationIdOptional. Setzt ein Gespräch fort, das du über die API begonnen hast, mit der conversationId einer früheren Antwort.
sessionIdOptional. Deine eigene ID für die Person, für die du chattest, zum Beispiel deine User-ID, bis zu 100 Zeichen. Derselbe Wert setzt immer dasselbe Gespräch fort. Du kannst auch die sessionId einer früheren Antwort senden.
streamOptional. true streamt den Text der Antwort; siehe Streaming. Standard ist false.
timeZoneOptional. Die IANA-Zeitzone der Person, zum Beispiel Europe/Berlin, für Terminzeiten. Ohne sie sind Zeiten in UTC.

Ohne conversationId und sessionId startet jede Nachricht ein neues Gespräch.

curl https://www.intochat.ai/api/v1/agents/AGENT_ID/chat \
  -H "Authorization: Bearer ic_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Do you ship to Switzerland?", "sessionId": "customer-4821" }'
{
  "reply": "Yes, we ship to Switzerland. Delivery takes 3 to 5 working days.",
  "conversationId": "CONVERSATION_ID",
  "sessionId": "icapi5f0c2b9e4d7a41f8a3c6e1b2d9f07a64",
  "sources": [
    { "title": "Shipping", "url": "https://www.example.com/shipping" }
  ],
  "followUps": ["How much does shipping cost?", "Can I track my order?"],
  "buttons": [],
  "products": [],
  "form": null,
  "leadForm": null,
  "booking": null,
  "liveChat": null
}
FeldInhalt
replyDie Antwort des Agenten als reiner Text mit Markdown, ohne die Steuerblöcke des Widgets. Leer, solange jemand aus deinem Team den Chat übernommen hat (siehe liveChat).
conversationIdDas Gespräch, wie unter Gespräch abrufen.
sessionIdDie Sitzung des Gesprächs in intoCHAT. Sie beginnt immer mit icapi.
sourcesDie Seiten, auf die sich die Antwort stützt, als title und url, wenn Show sources under replies eingeschaltet ist. Seiten aus der Websuche stehen immer in der Liste, mit "web": true.
followUpsVorgeschlagene nächste Fragen, wenn Suggest follow-up questions eingeschaltet ist.
buttonsEigene Buttons, die der Agent gewählt hat, als label und url.
productsProduktkarten aus deinem Shop oder aus API-Aktionen, mit name, url und, sofern bekannt, image, price, compareAtPrice, currency und available.
formEin Chat-Formular, das der Agent angeboten hat, mit formId, name, fields und submitLabel, oder null. Die API kann es nicht abschicken; zeig es in deiner eigenen Oberfläche oder ignoriere es.
leadFormDas Lead-Formular mit message, den Kontakt-fields und form, wenn der Agent nach Kontaktdaten gefragt hat, oder null. Kontaktdaten, die in einer Nachricht stehen, werden wie im Widget als Lead gespeichert, wenn Save contact details written in the chat eingeschaltet ist.
bookingFreie Terminzeiten mit provider, eventTitle, eventLength in Minuten, timeZone und days, jeweils mit date und slots als UTC-Zeiten, oder null. Die API kann keinen Termin buchen.
liveChatnull oder der Status des Live-Chats: offered (der Agent darf dein Team bitten dazuzukommen), requested (er hat es gebeten) oder paused (ein Teammitglied hat den Chat übernommen, deshalb hat der Agent nicht geantwortet).

Wie sich API-Chats vom Widget unterscheiden

  • Das Gespräch wird wie ein Widget-Chat gespeichert und erscheint im Tab Conversations des Agenten, mit seinen Leads, Bewertungen und Statistiken. Es hat kein Land und keine Seite.
  • Erlaubte Domains, gesperrte Länder und Nachrichten pro Besucher gelten nicht: Es gibt keine Seite und keine Adresse eines Besuchers, die sich prüfen ließe. Die Nachrichten deines Plans, das monatliche Limit des Agenten und das Ratenlimit des Schlüssels gelten.
  • Ein privater Agent lehnt API-Chats mit agent_private ab.
  • Client-seitige Aktionen laufen im Browser eines Besuchers, deshalb bekommt der Agent sie in API-Chats nicht angeboten. API-Aktionen, Buttons, Formulare und Terminbuchung funktionieren.
  • Dateien lassen sich nicht anhängen, und es gibt keine temporären Chats.
  • Nur Gespräche, die über die API begonnen wurden, lassen sich über die API fortsetzen. Der Agent sieht die letzten 40 Nachrichten des Gesprächs als Verlauf.
  • Solange jemand aus deinem Team den Chat im Live-Chat-Posteingang übernommen hat, wird deine Nachricht gespeichert, reply ist leer und liveChat ist paused. Die Antworten des Teammitglieds erscheinen im Gespräch: Lies sie mit Gespräch abrufen, dort haben sie einen authorName. Eine Nachricht während einer Übernahme verbraucht keine Nachrichten deines Plans.
  • Eine Antwort, die länger als 55 Sekunden dauert, endet mit einem Fehler 504 und dem Code timeout. Sie kann trotzdem als Nachricht zählen.

Streaming

Mit "stream": true ist die Antwort der Text der Antwort, während er geschrieben wird, als text/plain, ohne die JSON-Felder. Die Header X-Conversation-Id und X-Session-Id enthalten Gespräch und Sitzung, und X-Live-Chat den Live-Chat-Status, falls es einen gibt. Quellen, Buttons und die anderen Blöcke werden nicht gestreamt; lies sie danach mit Gespräch abrufen. Fehler kommen als JSON, wie ohne Streaming.

curl -N https://www.intochat.ai/api/v1/agents/AGENT_ID/chat \
  -H "Authorization: Bearer ic_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "What are your opening hours?", "stream": true }'

Gespräche auflisten

GET /api/v1/agents/{agentId}/conversations · Scope conversations:read

Die Gespräche des Agenten aus dem Widget und der API, die neuesten zuerst, ohne ihre Nachrichten. Nimmt limit, cursor und since an; siehe Paginierung.

curl "https://www.intochat.ai/api/v1/agents/AGENT_ID/conversations?limit=50&since=2026-10-01T00:00:00Z" \
  -H "Authorization: Bearer ic_live_YOUR_KEY"
{
  "data": [
    {
      "id": "CONVERSATION_ID",
      "sessionId": "8f14e45f-ceea-467a-9575-1a2b3c4d5e6f",
      "channel": "widget",
      "createdAt": "2026-10-04T09:00:00.000Z",
      "lastActivityAt": "2026-10-04T09:12:00.000Z",
      "country": "CH",
      "page": "https://www.example.com/pricing",
      "messageCount": 6,
      "topics": ["Pricing"],
      "sentiment": "positive",
      "liveChat": null,
      "csatScore": null
    }
  ],
  "hasMore": false,
  "nextCursor": null
}

channel ist api bei einem Gespräch, das über die API begonnen wurde, sonst widget (Script-Tag, Inline-iframe, Direktlink und Playground). topics und sentiment setzt die Themenanalyse, wenn sie eingeschaltet ist. liveChat ist null, requested, active oder ended. csatScore ist die Bewertung des Besuchers von 1 bis 5 nach einem Live-Chat oder null.

Gespräch abrufen

GET /api/v1/conversations/{conversationId} · Scope conversations:read

Ein Gespräch eines beliebigen Agenten im Konto, mit allen Nachrichten der Reihe nach.

{
  "data": {
    "id": "CONVERSATION_ID",
    "agentId": "AGENT_ID",
    "sessionId": "icapi5f0c2b9e4d7a41f8a3c6e1b2d9f07a64",
    "channel": "api",
    "createdAt": "2026-10-04T09:00:00.000Z",
    "lastActivityAt": "2026-10-04T09:14:00.000Z",
    "country": null,
    "page": null,
    "topics": [],
    "sentiment": null,
    "handoffRequestedAt": null,
    "liveChat": { "status": "ended", "startedAt": "2026-10-04T09:05:00.000Z", "endedAt": "2026-10-04T09:13:00.000Z" },
    "csat": { "score": 5, "comment": "Quick and friendly.", "ratedAt": "2026-10-04T09:14:00.000Z" },
    "messages": [
      { "id": "MESSAGE_ID", "role": "assistant", "content": "Hello! How can I help you today?", "createdAt": "2026-10-04T09:00:00.000Z", "authorName": null, "sources": [] },
      { "id": "MESSAGE_ID", "role": "user", "content": "Can I change my delivery address?", "createdAt": "2026-10-04T09:01:00.000Z", "authorName": null, "sources": [] },
      { "id": "MESSAGE_ID", "role": "assistant", "content": "Yes, I'm on it. What's your order number?", "createdAt": "2026-10-04T09:06:00.000Z", "authorName": "Anna", "sources": [] }
    ]
  }
}

role ist user für den Besucher oder deine API-Nachrichten und assistant für den Agenten und dein Team. authorName ist der Vorname des Teammitglieds, das eine Antwort im Live-Chat geschrieben hat, oder null, wenn der Agent sie geschrieben hat. content ist der Text ohne die Steuerblöcke des Widgets; die sources einer Antwort des Agenten listen die Seiten auf, die sie gezeigt hat. handoffRequestedAt ist der Zeitpunkt, zu dem der Agent das Gespräch per E-Mail an dein Team geschickt hat, oder null. liveChat und csat sind null, wenn es keinen Live-Chat oder keine Bewertung gab.

Leads auflisten

GET /api/v1/agents/{agentId}/leads · Scope leads:read

Die Leads des Agenten, die neuesten zuerst. Nimmt limit, cursor und since an; siehe Paginierung.

{
  "data": [
    {
      "id": "LEAD_ID",
      "email": "jane@example.com",
      "phone": null,
      "name": "Jane",
      "customFields": [{ "id": "FIELD_ID", "label": "Company", "value": "Acme" }],
      "source": "form",
      "conversationId": "CONVERSATION_ID",
      "collectedAt": "2026-10-04T09:03:00.000Z",
      "lastSeenAt": "2026-10-04T09:03:00.000Z",
      "submissionCount": 1
    }
  ],
  "hasMore": false,
  "nextCursor": null
}

source ist form für das Lead-Formular oder chat für Kontaktdaten, die in einer Nachricht standen. customFields nutzt die Beschriftungen, die dein Formular jetzt hat. lastSeenAt und submissionCount ändern sich, wenn dieselbe Person erneut absendet. conversationId ist null, wenn das Gespräch gelöscht wurde.

Kontakte

Die Kontakte eines Agenten: verifizierte Besucher, Leads, importierte Kontakte und die, die du hier hinzufügst, jeder mit bis zu 50 eigenen Attributen. Zum Lesen braucht es leads:read, zum Anlegen, Ändern und Löschen contacts:write. Schlüssel, die mit Every scope erstellt wurden, haben beide.

Ein Kontakt sieht so aus:

{
  "id": "CONTACT_ID",
  "agentId": "AGENT_ID",
  "externalId": "user-4711",
  "email": "jane@example.com",
  "phone": "+41441234567",
  "name": "Jane",
  "attributes": { "plan": "pro", "seats": 5, "vip": true },
  "source": "api",
  "firstSeenAt": "2026-10-04T09:03:00.000Z",
  "lastSeenAt": "2026-10-04T09:03:00.000Z",
  "createdAt": "2026-10-04T09:03:00.000Z",
  "updatedAt": "2026-10-04T09:03:00.000Z"
}

source ist identity, lead, import oder api: woher der Kontakt ursprünglich kam. externalId ist die User-ID der Person auf deiner Website. E-Mail-Adressen werden in Kleinbuchstaben gespeichert.

Kontakte auflisten

GET /api/v1/agents/{agentId}/contacts · Scope leads:read

Die Kontakte des Agenten, die neuesten zuerst. Nimmt limit, cursor und since an (Kontakte, die zu oder nach diesem Zeitpunkt geändert wurden); siehe Paginierung. Mit email= oder external_id= suchst du einen einzelnen Kontakt.

curl "https://www.intochat.ai/api/v1/agents/AGENT_ID/contacts?external_id=user-4711" \
  -H "Authorization: Bearer ic_live_YOUR_KEY"
{ "data": [ { "id": "CONTACT_ID", "externalId": "user-4711", "email": "jane@example.com", "attributes": { "plan": "pro" } } ], "hasMore": false, "nextCursor": null }

data hat alle oben gezeigten Felder; hier fehlen einige.

Kontakt anlegen oder aktualisieren

POST /api/v1/agents/{agentId}/contacts · Scope contacts:write

curl https://www.intochat.ai/api/v1/agents/AGENT_ID/contacts \
  -H "Authorization: Bearer ic_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "external_id": "user-4711", "email": "jane@example.com", "name": "Jane", "attributes": { "plan": "pro", "seats": 5 } }'
FeldInhalt
external_idBis zu 200 Zeichen. Sende dieses Feld oder email.
emailEine gültige E-Mail-Adresse.
phone7 bis 15 Ziffern, optional mit + am Anfang.
nameBis zu 100 Zeichen.
attributesEin Objekt aus Attributnamen und Werten. Namen beginnen mit einem Kleinbuchstaben und bestehen aus Kleinbuchstaben, Ziffern und Unterstrichen, bis zu 40 Zeichen; siehe Attribute. Ein Wert ist Text mit bis zu 1.000 Zeichen, eine Zahl oder true/false, und null entfernt das Attribut.

Aktualisiert wird der Kontakt mit dieser external_id, sonst der mit dieser email, sonst wird ein neuer Kontakt angelegt. Ein Kontakt nur mit E-Mail-Adresse, der so gefunden wird, bekommt die external_id. Die Felder, die du sendest, ersetzen die gespeicherten, ein Feld mit null wird geleert, und Felder, die du weglässt, bleiben, wie sie sind. Attribute werden zusammengeführt: Die gesendeten werden gesetzt, die anderen bleiben erhalten.

{ "data": { "id": "CONTACT_ID", "externalId": "user-4711", "email": "jane@example.com", "attributes": { "plan": "pro", "seats": 5 } }, "result": "created" }

result ist created (Status 201) oder updated (Status 200). Eine E-Mail-Adresse, die zu einem Kontakt mit einer anderen External ID gehört, oder eine External ID oder E-Mail-Adresse, die ein anderer Kontakt schon hat, bekommt einen Fehler 409 mit dem Code conflict. Ein neuer Kontakt über die Kontakte pro Agent deines Plans hinaus bekommt einen Fehler 403 mit dem Code contact_limit_reached.

Kontakt abrufen

GET /api/v1/contacts/{contactId} · Scope leads:read

Ein Kontakt eines beliebigen Agenten im Konto, als { "data": { … } }.

Kontakt ändern

PATCH /api/v1/contacts/{contactId} · Scope contacts:write

Nimmt dieselben Felder an wie Kontakt anlegen oder aktualisieren, alle optional, und antwortet mit dem Kontakt als { "data": { … } }. Ein Kontakt muss eine External ID, eine E-Mail-Adresse oder eine Telefonnummer behalten.

Kontakt löschen

DELETE /api/v1/contacts/{contactId} · Scope contacts:write

{ "data": { "id": "CONTACT_ID", "deleted": true } }

Die Leads und Gespräche des Kontakts bleiben erhalten.

Quellen auflisten

GET /api/v1/agents/{agentId}/sources · Scope sources:read

Die Wissensquellen des Agenten in der Reihenfolge seines Tabs Knowledge, mit dem Trainingsfortschritt. Der Text einer Quelle ist nicht enthalten, außer Frage und Antwort eines Q&A-Paars.

{
  "data": [
    {
      "id": "SOURCE_ID",
      "type": "qa",
      "title": "Do you ship to Switzerland?",
      "url": null,
      "filename": null,
      "question": "Do you ship to Switzerland?",
      "answer": "Yes, in 3 to 5 working days.",
      "characters": 71,
      "status": "trained",
      "error": null,
      "trainedAt": "2026-10-02T09:00:00.000Z",
      "createdAt": "2026-10-02T08:59:00.000Z",
      "updatedAt": "2026-10-02T09:00:00.000Z"
    }
  ],
  "training": { "total": 18, "trained": 18, "pending": 0, "processing": 0, "failed": 0, "done": true },
  "characters": { "used": 48210, "limit": 500000 }
}

type ist website, file, text, qa oder notion. status ist pending, processing, trained oder failed, mit dem Grund in error. characters.limit sind die Trainingszeichen pro Agent in deinem Plan.

Quelle hinzufügen

POST /api/v1/agents/{agentId}/sources · Scope sources:write

Fügt einen Textbaustein oder ein Q&A-Paar hinzu und startet das Training, wie im Tab Knowledge. Der Agent nutzt die neue Quelle, sobald sie trainiert ist; verfolge ihren status mit Quellen auflisten.

Ein Textbaustein:

curl https://www.intochat.ai/api/v1/agents/AGENT_ID/sources \
  -H "Authorization: Bearer ic_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "type": "text", "title": "Opening hours", "content": "We are open Monday to Friday, 9:00 to 17:00." }'

Ein Q&A-Paar:

{ "type": "qa", "question": "Do you ship to Switzerland?", "answer": "Yes, in 3 to 5 working days." }
{
  "data": { "id": "SOURCE_ID", "type": "text", "title": "Opening hours", "status": "pending", "characters": 44 },
  "result": "created",
  "training": { "total": 19, "trained": 18, "pending": 1, "processing": 0, "failed": 0, "done": false }
}

data hat alle Felder aus Quellen auflisten; oben fehlen einige. result ist created (Status 201), updated, wenn es schon ein Q&A-Paar mit derselben Frage gab, ohne Rücksicht auf Groß- und Kleinschreibung, das jetzt die neue Antwort hat, oder unchanged, wenn es genau diese Antwort schon hatte (beide Status 200). Ein Textbaustein wird immer als neue Quelle hinzugefügt. Ein Titel und eine Frage können jeweils bis zu 200 Zeichen lang sein.

Die Quelle zählt auf die Trainingszeichen des Agenten. Eine Quelle, die das Limit deines Plans überschreiten würde, bekommt einen Fehler 403 mit dem Code character_limit_exceeded, und es wird nichts hinzugefügt. Siehe Trainingszeichen pro Agent.

Quelle löschen

DELETE /api/v1/agents/{agentId}/sources/{sourceId} · Scope sources:write

Löscht die Quelle und das, was der Agent daraus gelernt hat, sofort, wie das Löschen im Tab Knowledge. Sonst muss nichts neu trainiert werden.

{ "id": "SOURCE_ID", "deleted": true, "training": { "total": 17, "trained": 17, "pending": 0, "processing": 0, "failed": 0, "done": true } }

Webhook abonnieren

POST /api/v1/agents/{agentId}/webhooks · Scope webhooks:write

Abonniert einen Webhook für die Events des Agenten: einen REST-Hook, wie ihn die sofortigen Trigger von Zapier und Make nutzen. intoCHAT sendet dann jedes Event an die Adresse, wie unter Webhooks beschrieben, signiert und wiederholt wie bei einem Webhook, der im Tab Leads hinzugefügt wurde.

FeldInhalt
urlPflicht. Die Adresse, an die die Events gehen. Wie im Tab Leads muss sie mit https:// beginnen und auf einen öffentlichen Server zeigen; private und interne Netzwerkadressen werden abgelehnt.
eventsPflicht. Eines oder mehrere von lead.created, handoff.requested, form.submitted, booking.created, live_chat.requested und return.requested. Siehe Events.
sourceOptional. zapier, make oder api (Standard): was der Tab Leads neben dem Webhook zeigt, zum Beispiel via Zapier.
curl https://www.intochat.ai/api/v1/agents/AGENT_ID/webhooks \
  -H "Authorization: Bearer ic_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://hooks.example.com/intochat", "events": ["lead.created"], "source": "api" }'
{
  "id": "WEBHOOK_ID",
  "agentId": "AGENT_ID",
  "url": "https://hooks.example.com/intochat",
  "events": ["lead.created"],
  "source": "api",
  "secret": "whsec_…",
  "createdAt": "2026-10-08T09:00:00.000Z"
}

Die Antwort hat den Status 201. Bewahre id auf, um das Abonnement später zu beenden. secret ist das Signing Secret des Webhooks und kommt nur hier zurück; nutze es, um die Signatur zu prüfen, wenn dein Empfänger das kann. Tools, die keine Signaturen prüfen können, etwa Zapier und Make, können es ignorieren.

Ein abonnierter Webhook erscheint im Tab Leads des Agenten mit dem Kennzeichen via Zapier, via Make oder via API, wo der Owner ihn pausieren oder entfernen kann. Er merkt sich den Schlüssel, der ihn abonniert hat: Widerrufst du diesen Schlüssel, wird er gelöscht. Ein Agent kann bis zu 25 abonnierte Webhooks haben, zusätzlich zu den 5, die im Tab Leads hinzugefügt werden; darüber hinaus bekommt die Anfrage einen Fehler 400.

Webhook abbestellen

DELETE /api/v1/webhooks/{webhookId} · Scope webhooks:write

Löscht einen Webhook, der über die API abonniert wurde, samt Zustellverlauf. Das kann jeder Schlüssel desselben Kontos. Ein Webhook, der im Tab Leads hinzugefügt wurde, der Webhook eines anderen Kontos oder einer, der schon entfernt wurde, bekommt 404.

{ "id": "WEBHOOK_ID", "deleted": true }

Events auflisten

GET /api/v1/agents/{agentId}/events/{event} · Scope agents:read, dazu leads:read oder conversations:read

Die letzten Events einer Art des Agenten, die neuesten zuerst, jedes genau so aufgebaut wie der Inhalt einer Webhook-Zustellung. Automatisierungstools fragen diesen Endpunkt regelmäßig ab, statt auf einen Webhook zu warten, zum Beispiel um echte Beispieldaten zu zeigen. Nimmt limit an, von 1 bis 100 (Standard 20).

eventBraucht außerdemAufgebaut aus
lead.createdleads:readLeads, die zuletzt gespeicherten zuerst
form.submittedleads:readFormulareinsendungen
booking.createdleads:readBuchungen
return.requestedleads:readRücksendeanfragen
handoff.requestedconversations:readGespräche, die per E-Mail übergeben wurden
live_chat.requestedconversations:readGespräche, in denen der Agent dein Team gebeten hat dazuzukommen
conversation.createdconversations:readNeue Gespräche. Für dieses Event gibt es keinen Webhook; es lässt sich nur auflisten.
curl "https://www.intochat.ai/api/v1/agents/AGENT_ID/events/lead.created?limit=5" \
  -H "Authorization: Bearer ic_live_YOUR_KEY"
{
  "data": [
    {
      "id": "LEAD_ID",
      "event": "lead.created",
      "created_at": "2026-10-07T09:30:00.000Z",
      "agent": { "id": "AGENT_ID", "name": "Acme Assistant" },
      "data": {
        "leadId": "LEAD_ID",
        "agentId": "AGENT_ID",
        "agentName": "Acme Assistant",
        "email": "jane@example.com",
        "phone": null,
        "name": "Jane",
        "customFields": [],
        "source": "form",
        "conversationId": "CONVERSATION_ID",
        "collectedAt": "2026-10-07T09:30:00.000Z"
      }
    }
  ]
}

Die Unterschiede zu einer Zustellung:

  • id ist die ID des Datensatzes, keine Zustell-ID, dasselbe Event hat also immer dieselbe id: die ID des Leads, der Einsendung, der Buchung, der Rücksendeanfrage oder des Gesprächs. Bei Übergaben und Live-Chat-Anfragen ist es die ID des Gesprächs, ein Doppelpunkt und die Zeit in Millisekunden, weil ein Gespräch später erneut fragen kann.
  • created_at ist der Zeitpunkt, zu dem der Datensatz gespeichert wurde.
  • Die Daten werden aus dem neu aufgebaut, was intoCHAT speichert. Die summary einer Übergabe wird nicht gespeichert, sie ist also null, und test ist false. Eine Übergabe, die ein Helpdesk-Ticket geöffnet hat, enthält ihr ticket, wie der Webhook. Das providerStatus einer Buchung ist pending, solange sie auf deine Bestätigung wartet, sonst accepted. Eine Rücksendeanfrage hat ihren aktuellen status, requested oder handled.
  • Die Daten von conversation.created haben conversationId, channel (widget oder api), page, country und createdAt.

Beispiel-Events abrufen

GET /api/v1/agents/{agentId}/events/{event}/samples · Scope agents:read

Bis zu 3 der letzten Events des Agenten, wie unter Events auflisten, damit ein Tool immer Daten hat, aus denen es Felder zuordnen kann. Hat der Agent noch keine, oder fehlt dem Schlüssel der Scope, den dieses Event braucht (leads:read oder conversations:read), kommt stattdessen ein dokumentiertes Beispiel mit denselben Feldern, und sample ist true.

{
  "data": [
    {
      "id": "sample_booking.created",
      "event": "booking.created",
      "created_at": "2026-10-07T09:30:00.000Z",
      "agent": { "id": "AGENT_ID", "name": "Acme Assistant" },
      "data": { "bookingId": "sample_booking", "eventTitle": "30 min intro call", "attendeeEmail": "jane@example.com" }
    }
  ],
  "sample": true
}

Die data des Beispiels haben alle Felder des Events; oben fehlen einige.

Grenzen

  • Die API ist ab Starter enthalten. Im Plan Free lassen sich keine Schlüssel erstellen, und bestehende bekommen plan_required.
  • 60 Anfragen pro Minute und Schlüssel, und höchstens 20 aktive Schlüssel pro Konto.
  • Jede Chat-Antwort zählt als eine Nachricht deines Plans. Ein Agent beantwortet höchstens 1.000 Nachrichten pro Stunde, Widget und API zusammen.
  • Eine Chat-Antwort muss innerhalb von 55 Sekunden fertig sein.
  • Quellen: nur Textbausteine und Q&A-Paare. Website-Seiten, Dateien und Notion-Seiten fügst du im Dashboard hinzu.
  • Bis zu 25 abonnierte Webhooks pro Agent, zusätzlich zu den 5, die im Tab Leads hinzugefügt werden.
  • Kontakte werden einzeln angelegt und aktualisiert. Um viele auf einmal hinzuzufügen, nutze CSV-Datei importieren im Dashboard.
  • Endpunkte zum Erstellen oder Ändern von Agenten, zum Abschicken von Formularen, zum Buchen von Terminen oder zum Übernehmen von Live-Chats gibt es noch nicht.

Wie es weitergeht

  • Lass dir Leads und Übergaben an deinen Server schicken, sobald sie passieren: Webhooks.
  • intoCHAT in Zapier oder Make nutzen: Zapier und Make.
  • Lass deinen Agenten beim Antworten deine eigene API aufrufen: API-Aktionen.
  • Schreib gute Textbausteine und Q&A-Paare: Text und Q&A.
  • Prüfe, was dein Plan enthält: Pläne und Limits.

Als Markdown anzeigen