Website-Chat-API
Verbinden Sie ein eigenes Formular mit dem Chat-Widget oder bauen Sie mit dem Widget-SDK, REST, Typen, SSE und Besucheraktivität eine eigene Chat-Oberfläche.
Zuletzt aktualisiert am
Das offizielle Widget installieren Sie in der App: siehe Den Chat auf Ihrer Website einbinden. Die Optionen des Snippets stehen unter Einstellungen des Website-Chats. Diese Seite richtet sich an Entwickler: das Widget-SDK für ein eigenes Formular und die REST-Schicht für eine eigene Chat-Oberfläche. Siehe OpenAPI, Tag inbox.
Widget-SDK
Nach dem Laden des Widget-Skripts steht window.TillorInbox bereit. Damit übergeben Sie Kontaktdaten aus Ihrem eigenen Formular (Kontaktseite, Verkaufsdetail, Angebotsanfrage). Alle Methoden warten, bis die Widget-Konfiguration geladen ist.
| Methode | Beschreibung |
|---|---|
ready() | Promise, die erfüllt ist, sobald das Widget geladen ist |
getVisitor() | Liest gespeicherte Kontaktdaten aus localStorage und ausgefüllte Widget-Felder; synchron, kein Netzwerk |
setVisitor({ name?, firstName?, lastName?, email?, phone?, message?, customFields? }, options?) | Füllt Chat-Felder aus, ohne zu senden |
open() | Öffnet das Chatfenster |
close() | Schließt das Chatfenster |
toggle() | Öffnet oder schließt das Chatfenster |
send({ body, name?, firstName?, lastName?, email?, phone?, message?, customFields?, open?, silent?, markSubmitted?, metadata? }) | Sendet eine Nachricht mit Kontaktdaten |
getVisitor() gibt dieses Objekt zurück:
| Feld | Beschreibung |
|---|---|
visitorId | ID dieses Besuchers in diesem Browser (localStorage) |
name | Vollständiger Name (ein Feld im Widget) |
firstName / lastName | Abgeleitet aus name (erstes Wort / Rest) |
email, phone | Kontaktdaten |
customFields | Zusätzliche Felder aus den Widget-Einstellungen |
message | Entwurf im Nachrichtenfeld |
detailsSubmitted | Ob das Besucherformular als ausgefüllt gilt |
Verwenden Sie getVisitor(), um ein eigenes Formular aus localStorage vorab auszufüllen (gleicher Browser, auch nach einem Neuladen der Seite).
Optionen für setVisitor (zweites Argument):
| Option | Standard | Erklärung |
|---|---|---|
open | false | Chatfenster sofort öffnen |
markSubmitted | false | Besucherformular ausblenden, wenn alle Pflichtfelder ausgefüllt sind |
onlyEmpty | false | Nur leere Felder überschreiben |
persist | false | Daten in localStorage speichern (gleicher Browser, auch nach einem neuen Tab) |
Optionen für send:
| Option | Standard | Erklärung |
|---|---|---|
open | false | Chatfenster vor dem Senden öffnen |
silent | true, wenn open false ist | Kein Ton, keine Fehlermeldung im Widget; verwenden Sie die Promise für Erfolg oder Fehler |
markSubmitted | true | Kontaktdaten müssen danach nicht erneut im Widget eingegeben werden |
metadata | - | Optionale Hinweise für Tillie (im Chatfenster nicht sichtbar); siehe metadata |
Mit open: false (Standard) bleibt die Chat-Schaltfläche geschlossen. Die Nachricht geht trotzdem an Tillor; Ihr eigenes Formular kann sich bedanken oder einen Fehler anzeigen. Mit open: true öffnet sich das Chatfenster, und der Besucher sieht das normale Sendeverhalten (Ton, Häkchen, eventuelle Widget-Fehler).
Möchten Sie statt der schwebenden Chat-Schaltfläche eine eigene Schaltfläche verwenden? Setzen Sie data-launcher="false" auf das Snippet und rufen Sie TillorInbox.open() auf.
metadata (Buchungsformular)
Verwenden Sie metadata, wenn Sie ein eigenes Formular auf der Website haben und Tillie nur eine Bestätigung senden soll, ohne Rückfragen (zum Beispiel, weil der Tab danach schließt).
| Schlüssel | Typ | Erklärung |
|---|---|---|
forceHandover | boolean | Bestätigungsnachricht und Übergabe an einen Kollegen, ohne Aufnahmefragen. Ignoriert auch die KI-Pause nach einer Teamnachricht (siehe ignoreAiPause) |
ignoreAiPause | boolean | Tillie antwortet auch dann, wenn sie im Modus Automatisch nach einer Teamnachricht pausiert ist (30 Minuten). Praktisch für stilles Absenden von Formularen; kombinieren Sie es mit forceHandover oder lassen Sie Tillie normal die Aufnahme machen |
handoverIntent | "reservation" | "caravan_rental" | "sale" | "other" | Optional: Ablauf für die Übergabe (Standard: automatisch aus der Nachricht ableiten) |
source | string | Optionale Integrationsbezeichnung für Ihr Team (Kleinbuchstaben, Ziffern, -, _; max. 64 Zeichen) |
await TillorInbox.send({
name: "Jan Janssens",
email: "jan@voorbeeld.be",
phone: "+32 3 779 81 64",
body: structuredBookingMessage,
silent: true,
metadata: {
forceHandover: true,
handoverIntent: "reservation",
source: "website_booking_form",
},
});Kontaktformular ersetzen (stilles Senden)
Verwenden Sie dies, wenn Sie das bestehende Kontaktformular behalten, die Nachrichten aber über Tillor laufen lassen möchten, ohne das Chatfenster zu öffnen.
<form id="site-contact-form">
<input name="name" type="text" required />
<input name="email" type="email" required />
<input name="phone" type="tel" />
<textarea name="message" required></textarea>
<button type="submit">Verstuur</button>
<p id="contact-status" hidden></p>
</form>
<script>
document.getElementById("site-contact-form").addEventListener("submit", async (event) => {
event.preventDefault();
const form = event.currentTarget;
const status = document.getElementById("contact-status");
const data = new FormData(form);
try {
await TillorInbox.send({
name: String(data.get("name") ?? ""),
email: String(data.get("email") ?? ""),
phone: String(data.get("phone") ?? ""),
body: String(data.get("message") ?? ""),
});
status.textContent = "Bedankt, we nemen snel contact op.";
status.hidden = false;
form.reset();
} catch (error) {
status.textContent = error instanceof Error ? error.message : "Versturen mislukt.";
status.hidden = false;
}
});
</script>open und silent müssen Sie nicht setzen: Ohne open: true bleibt das Fenster geschlossen, und Tillor behandelt den Aufruf als stilles Senden.
Kontaktformular verbinden (Chat öffnen)
Felder übergeben und das Chatfenster öffnen, damit der Besucher das Gespräch sieht:
<form id="site-contact-form">
<input name="name" type="text" required />
<input name="email" type="email" required />
<input name="phone" type="tel" />
<textarea name="message" required></textarea>
<button type="submit">Verstuur</button>
</form>
<script>
document.getElementById("site-contact-form").addEventListener("submit", (event) => {
event.preventDefault();
const form = event.currentTarget;
const data = new FormData(form);
void TillorInbox.send({
name: String(data.get("name") ?? ""),
email: String(data.get("email") ?? ""),
phone: String(data.get("phone") ?? ""),
body: String(data.get("message") ?? ""),
open: true,
});
});
</script>Oder nur Felder ausfüllen und das Fenster öffnen, ohne sofort zu senden:
void TillorInbox.setVisitor(
{
name: "Jan Janssens",
email: "jan@voorbeeld.be",
phone: "+32 3 779 81 64",
message: "Ik heb een vraag over de stacaravan te koop.",
},
{ markSubmitted: true, open: true },
);Eine Verkaufsseite mit sofortigem Senden und Öffnen des Chats:
void TillorInbox.send({
name: "Jan Janssens",
email: "jan@voorbeeld.be",
phone: "+32 3 779 81 64",
body: "Ik heb interesse in deze stacaravan.",
open: true,
});Live synchronisieren, während jemand tippt:
const form = document.getElementById("site-contact-form");
form.addEventListener("input", () => {
void TillorInbox.setVisitor({
name: form.name.value,
email: form.email.value,
phone: form.phone.value,
message: form.message.value,
});
});Früh aufrufen (vor dem Widget-Skript)
Rufen Sie eine Methode auf, bevor das Skript geladen ist, stellen Sie den Aufruf in die Warteschlange:
<script>
window.TillorInbox = window.TillorInbox || { q: [] };
window.TillorInbox.q.push([
"setVisitor",
{ name: "Jan", email: "jan@voorbeeld.be" },
{ open: true },
]);
</script>
<script src="https://tillor.eu/inbox-widget.js" data-org-id="org_abc123" data-widget-key="iwk_xxx" async defer></script>Eigene Chat-Oberfläche
Bauen Sie eine eigene Chat-Oberfläche statt des Widgets, verwenden Sie die REST-Schicht unten.
Authentifizierung: Header X-Tillor-Inbox-Widget-Key (Wert aus Einstellungen > Integrationen > Website-Chat).
Tippen
POST /api/orgs/{orgId}/inbox/website/typing
X-Tillor-Inbox-Widget-Key: iwk_xxx
Content-Type: application/json
{
"visitorId": "vis_…",
"active": true,
"visitorName": "Jan",
"visitorEmail": "jan@voorbeeld.nl",
"visitorPhone": "+32470123456"
}active: true, wenn der Besucher tippt;false, wenn das Feld leer ist oder der Besucher aufhört (das Widget sendetfalsenach etwa 4 Sekunden ohne Eingabe)visitorName/visitorEmail/visitorPhonesind optional- Verwenden Sie dieselbe
visitorIdwie beiPOST …/inbox/website/messagesundGET …/inbox/website/messages
Echtzeit (SSE)
GET /api/orgs/{orgId}/inbox/website/subscribe?visitorId=vis_…
X-Tillor-Inbox-Widget-Key: iwk_xxx
Accept: text/event-stream| Event | Wann |
|---|---|
inbox:website:message-created | Neue Team- oder KI-Nachricht |
inbox:website:message-updated | Team- oder KI-Nachricht geändert oder gelöscht |
inbox:website:typing-changed | data.staffTyping oder data.staffOutboundSenderType ändert sich |
Die Payload-Form ist dieselbe wie bei Org-SSE (event, data, timestamp). Verbinden Sie sich nach einem Abbruch neu; es gibt kein Wiederaufsetzen.
Das offizielle Widget verwendet SSE als primäre Schicht und ruft GET …/messages alle 5 Sekunden erneut ab, als Fallback (alle 1 Sekunde bei geöffnetem Panel, wenn SSE kurz ausfällt). Dadurch werden Antworten als zugestellt markiert, solange der Besucher auf der Seite ist.
Besucheraktivität
POST /api/orgs/{orgId}/inbox/website/events
X-Tillor-Inbox-Widget-Key: iwk_xxx
Content-Type: application/jsonevent: chat_closed, tab_hidden oder navigation (bei Navigation auch url). Ihr Team sieht diese Ereignisse als grauen Infotext im Gespräch, siehe Gespräche über den Website-Chat.
Limits
POST …/inbox/website/messages und POST …/inbox/website/attachments/upload antworten mit 429, wenn ein Besucher oder ein Netzwerk zu viel sendet. Der Body enthält data.reason = INBOX_WIDGET_RATE_LIMITED und data.retryAfterSeconds. Limits pro Organisation:
| Route | Pro Besucher (visitorId) | Pro Netzwerk (IP-Adresse) |
|---|---|---|
messages | 10 pro Minute, 200 pro Tag | 30 pro Minute, 600 pro Tag |
attachments/upload | 10 pro Stunde | 50 pro Stunde |
Warte retryAfterSeconds, bevor du es erneut versuchst, und zeig dem Besucher eine Meldung, statt automatisch zu wiederholen.