Skip to content
XICBOT

Settings

Deutsch
Documentation · Tools and actions

Tool kit for custom connections

Client, signature check and stream reader in Node, PHP and Python: call the API, verify webhooks and answer calls from XICBOT to your system.

In plain language

This page is for developers. The kit is program code for your own connection. It comes in three programming languages. With it you talk to the interface. You can read an answer while it is being written. You can check that a message to your system is genuine. The page also explains the other direction. Then the assistant calls your system.

Last updated

All documentation topics

The tool kit is source code for your own connection to XICBOT, in three editions: Node (js/), PHP (php/) and Python (python/), each with four files. It contains a client for the API-key interface, a reader for the event stream of a chat reply, the signature check for webhooks and the lists of event types. It needs no further packages: Node calls via fetch, PHP via the curl extension, Python via the standard library. The last section covers the opposite direction: what your system has to answer when an assistant calls it as a tool.

What the kit contains

TaskNode (js/)PHP (php/)Python (python/)
Client for the interfaceklient.mjs: class Klientklient.php: class XicbotKlientklient.py: class Klient
Event stream readerstrom.mjs: class Stromstrom.php: class XicbotStromstrom.py: class Strom
Webhook signature checksignatur.mjs: signaturPruefen()signatur.php: xicbot_signatur_pruefen()signatur.py: signatur_pruefen()
Name of the signature headerSIGNATURKOPFXICBOT_SIGNATURKOPFSIGNATURKOPF
Event typesereignisse.mjs: STROM_EREIGNISSE, RUECKRUF_EREIGNISSEereignisse.php: XICBOT_STROM_EREIGNISSE, XICBOT_RUECKRUF_EREIGNISSEereignisse.py: STROM_EREIGNISSE, RUECKRUF_EREIGNISSE
Calls viafetch, signature with node:cryptocurl extensionurllib.request, signature with hmac

Each file names in its header the version of the interface description it was generated from, so you can tell which state of the API your copy reflects. The client loads the stream reader from the same directory (./strom.mjs, strom.php, from strom import Strom), so keep the files of one language together. The signature check and the event lists stand on their own and can be taken over individually, for example into a receiver that only accepts webhooks.

Address and key

The client takes two values: the base address https://app.xicbot.de and an API key. Trailing slashes on the base address are removed; the client appends the paths (/api/v1/integration/…) itself. If the base address is missing, all three editions stop with Basisadresse fehlt as soon as the client is created. The client sends the key in the X-Api-Key header. It starts with xbot_; a value without that prefix counts as missing.

StatusField errorMeaning
400key_in_urlKey sent as a parameter in the address
401key_missingHeader X-Api-Key missing, empty or not starting with xbot_
401invalid_keyKey unknown, revoked or expired; all three cases answer the same way
402plan_feature_missingThe account's plan does not include the feature for keys and webhooks, for example after a plan change; available_in lists the plans that include it
403tenant_suspendedThe account behind the key is not active
403scope_missingThe key lacks the scope the call needs, for example leads or chat; the required field names it
403read_onlyThe key lacks the writing scope (leads.write, knowledge.write); required names it
429too_many_requestsPer-minute or daily cap reached, see Limits

Creating a key

  1. Step 1

    Open the page

    Keys and webhooks are under Administration › Interfaces (app.xicbot.de/schnittstellen). The menu item appears for the Administration and Owner roles; only these roles create and revoke keys. The roles are described in Team, roles and audit log.

  2. Step 2

    Choose name and scopes

    In the API keys section enter a Name of at most 80 characters and tick at least one scope under Scopes; until then Create a new key stays disabled. Below the scopes it says: “Writing is a separate scope. Without it a key only reads.”

  3. Step 3

    Set limit and expiry

    Requests per minute is a required field from 1 to 6000, preset to 120. Expires in days accepts 1 to 3650; below it the page says “Empty means no expiry.” The expiry date is calculated from the number of days when the key is created.

  4. Step 4

    Copy the key

    After Create a new key the card Your new key shows the value: xbot_ followed by 48 characters. Below it: “Copy it now. After closing it cannot be retrieved again.” The Copy key button puts it on the clipboard; if that fails, the page says “The clipboard is not available here. Select the value and copy it manually.” Of the key itself, XICBOT stores only a SHA-256 fingerprint and the Identifier, the first 12 characters.

The key list shows Name, Identifier, Scopes, Last used, Expires (no limit for keys without expiry), Status with valid, expired or revoked, and Action. Last used is updated at most once a minute. Next to the create button a counter shows the valid keys, for example 3 / 10. At most ten keys can be valid at the same time; the eleventh is refused with 422, too_many_keys and the message “The maximum number of simultaneous keys has been reached.” Revoked and expired keys do not count.

Revoke asks for confirmation in the row: “Revoke this key? Requests using it will be rejected from then on.” Confirm with Revoke or back out with Cancel. From then on the API answers this key with 401 and invalid_key; the row stays in the list with the status revoked. A key cannot be edited. For other scopes or another limit, create a new key, switch your system over and revoke the old one. More on managing keys is in API keys and webhooks.

Scopes

ScopeIn the appAllows
conversationsRead conversationsList conversations and read one conversation with its messages in plain text
leadsRead enquiriesList enquiries
leads.writeCreate enquiriesCreate an enquiry
appointmentsRead appointmentsList appointments
analyticsRead analyticsRetrieve metrics for 7, 30 or 90 days
knowledge.writeCreate knowledge sourcesCreate a knowledge source from text or an address
chatUse chatAsk an assistant a question and read the reply as a stream
none–Any valid key gets an answer from GET /api/v1/integration/status

A writing scope does not include the reading one: leads.write creates enquiries but does not read them. GET /api/v1/integration/status returns alive, the account identifier in tenant, the key's scopes in scopes and its per-minute limit in limit_per_min. This lets you test a connection without reading any data. The individual requests are described in Integration endpoints.

Limits

Each key has its own per-minute cap, the value from Requests per minute. On top of that there is a daily cap from your account. It is counted per key and calendar day and expires at midnight, not 24 hours after the first request; a daily cap of 0 means no daily cap. Both caps are checked before either is counted, so a request rejected at a cap consumes nothing. GET /api/v1/integration/status counts as well. The level of the daily cap is given in the limit field of a 429 reply with scope day; GET /api/v1/integration/status only reports the per-minute cap as limit_per_min.

Field of the 429 responseContent
errortoo_many_requests
scopeminute or day: which cap applied
limitValue of that cap
retry_afterSeconds until a retry makes sense; the same value is in the Retry-After header
limit_per_minThe key's per-minute cap, even when the daily cap applied
waitSame value as retry_after

On 429 the client throws an error with the status and body of the response; you build retrying after retry_after yourself. The reply quota is separate: once it is used up for the month, the chat answers with 429 and quota_exhausted, see Chat and event stream. Overview of all limits: API limits.

The client

The client maps each operation of the API to a method of its own, named after the HTTP method and the path. You create it with the base address, the key and a timeout; the timeout limits every call whose reply arrives in one piece.

ItemNodePHPPython
Creating itnew Klient(basis, schluessel, frist)new XicbotKlient($basis, $schluessel, $frist)Klient(basis, schluessel, frist, stream_timeout)
Default timeout15000 milliseconds15 seconds15 seconds
Read timeout for chatnonenonestream_timeout, 120 seconds per read by default
Empty base addressError with Basisadresse fehltInvalidArgumentException with Basisadresse fehltValueError with Basisadresse fehlt
Method naminggetStatus(), postLeads(daten)getStatus(), postLeads($daten)get_status(), post_leads(daten)
Return value (except chat)Promise with the parsed JSONarraydictionary

The Node and PHP editions set no timeout for chat, because the stream runs for as long as the reply is being produced. The Python edition reads the stream line by line and stops when a single read waits longer than stream_timeout for data, 120 seconds by default. Every request carries Content-Type: application/json, Accept: application/json and the key in X-Api-Key; for chat the client asks for text/event-stream instead.

Method (Node, PHP)Method (Python)OperationScopeRequired by the client
getStatus()get_status()GET /api/v1/integration/statusnone–
getConversations(page)get_conversations(page)GET /api/v1/integration/conversationsconversations–
getConversationsId(id)get_conversations_id(id)GET /api/v1/integration/conversations/{id}conversations–
getLeads(page)get_leads(page)GET /api/v1/integration/leadsleads–
postLeads(daten)post_leads(daten)POST /api/v1/integration/leadsleads.writesubject
getAppointments(page)get_appointments(page)GET /api/v1/integration/appointmentsappointments–
getAnalytics(period, zone)get_analytics(period, zone)GET /api/v1/integration/analyticsanalytics–
postKnowledgeSources(daten)post_knowledge_sources(daten)POST /api/v1/integration/knowledge/sourcesknowledge.writetitle; text or url
postChat(daten, leser)post_chat(daten, leser)POST /api/v1/integration/chatchatassistant_id, text

If a required field is missing, the client stops before sending and raises Pflichtfeld fehlt: <field> as Error (Node), InvalidArgumentException (PHP) or ValueError (Python). When creating a knowledge source it also requires text or url and otherwise raises Eines der Felder fehlt: text oder url. XICBOT checks every other rule itself and answers a violation with 422. Conversations and enquiries are returned newest first, appointments by start time with the latest first. The three lists return 50 entries per call; page picks the page, counting from 1, and a missing or smaller value counts as 1. Keep reading until a page holds fewer than 50 entries. getAnalytics takes an IANA time zone in zone, default Europe/Berlin; XICBOT answers an unknown zone with 422 and unknown_timezone. A single conversation returns up to 200 messages in chronological order, each with role, text and time; an unknown ID is answered with 404 and not_found.

What XICBOT validates

OperationFieldRule
Create enquirysubjectrequired, at most 1000 characters
Create enquirynameat most 120 characters
Create enquiryemailvalid email address, at most 190 characters
Create enquiryphoneat most 60 characters
Create enquirysourceat most 60 characters; api if omitted
Create enquiryexternal_idat most 100 characters; prevents duplicate entries
Create knowledge sourcetitlerequired, at most 200 characters
Create knowledge sourcetextrequired if url is missing; at most 400000 characters
Create knowledge sourceurlrequired if text is missing; valid address, at most 500 characters
Create knowledge sourcedraft, published_atonly together with text; draft is true or false, published_at a date
Analyticsperiod7d, 30d or 90d; 30d if omitted
Chatassistant_idrequired, at most 64 characters
Chatconversation_idat most 64 characters; continues a conversation
Chattextrequired, 1 to 4000 characters; the account can set a lower limit

XICBOT answers a new enquiry with 201, the entry under lead and duplicate_prevented: false, and sends the lead.created webhook at the same time. If the same external_id arrives a second time, no second entry is created: the reply is 200 with the existing entry and duplicate_prevented: true. After a timeout, resend with the same external_id. How enquiries are handled in the app is described in Appointments and cases.

A knowledge source with text is processed straight away; the reply is 201 with id, type (text), status and chunks under source, and knowledge.indexed or knowledge.failed is sent. The 201 also comes back when processing failed, so check status (ready means success). A source with url is created with 202 and, under source, id, type website and status new, and the page is fetched in the background. As when a source is created in the app, XICBOT also queues a background job for both kinds that enriches the sections and builds their vectors; after that, search usually finds the source by meaning as well, not only by matching words. Addresses that do not point to the public internet are rejected with 422 and the reason in error, for example target_not_allowed. More about sources is in Maintain knowledge.

Errors in the client

CaseNodePHPPython
Status 400 or higherError: Antwort <status>: <text>RuntimeException: Antwort <status>: <text>RuntimeError: Antwort <status>: <text>
No connection or timeout expirederror from fetch, a TimeoutError for the timeoutRuntimeException: Aufruf fehlgeschlagen: …RuntimeError: Aufruf fehlgeschlagen: …
Reply is not JSONempty object {}empty array []empty dictionary {}
Chat with status 400 or higherError: Antwort <status>: <text>RuntimeException: Antwort <status>: <text>RuntimeError: Antwort <status>: <text>
Chat transfer interruptedstream error; without a body Antwort ohne StromRuntimeException: Strom abgebrochen: …RuntimeError: Strom abgebrochen: …, also when the read timeout expires

The text after the status is the body of the error reply, which XICBOT sends as JSON with an error field. The values are explained in the table under Address and key and in the chat section.

Chat and event stream

POST /api/v1/integration/chat

Asks an assistant a question and returns the answer as an event stream (text/event-stream). Without conversation_id a new conversation starts; with it, a conversation continues that the same assistant began through the API.

Authentication
X-Api-Key header, scope chat
Rate limit
The key's per-minute and daily caps, plus the account's monthly quota

Each event consists of an event: <type> line, one or more data: <JSON> lines and a blank line. The kit's stream reader hands an event over only once the blank line has arrived, joins several data lines with a line break, strips a trailing \r and passes type and data to your function. If the content is not valid JSON, the data arrives as null (Python: None).

StatusField errorMeaning
404not_foundUnknown assistant, or conversation_id is not an API conversation of this assistant
409reply_in_progressA reply is currently being produced for this conversation
413input_too_longText longer than the account limit; limit and length give both values. No new conversation is created
422no_versionThe assistant has no published version yet
429quota_exhaustedMonthly quota used up; scope is month, retry_after and the Retry-After header give the seconds until the month changes. XICBOT usually removes a conversation that only this call started

A conversation that started in the widget or in a test chat cannot be continued through the API, not even with the conversations scope; XICBOT answers with 404. How much the account may answer per month is described in Plans, quotas and billing.

Event types

TypeFieldsMeaning
startconversation_id, question_idThe reply begins; you need conversation_id to continue
texttA piece of reply text; concatenated, the pieces form the reply
redactiontext, reason, count (only with claims)Replaces the text collected so far with text; reason is claims (correction of unsupported statements) or notice. Append any text pieces that follow
citationscitationsThe sources used in the reply
verificationstate, claims, totalResult of the check against the knowledge
enforcementstate, topics, handoverResult of the check against the assistant rules
follow_upsquestions, dropped, checked, reasonSuggested follow-up questions
contact_offerofferedThe reply offers to get in touch
handoffhandoff, reasonHandover to a person; reason is for example assistant, conversation_limit or enforcement
livelive, sinceA person has taken over the conversation; end with live follows
fallbackreason, transientThe reply failed; the stored fallback reply follows as text
revokedreasonConsent was withdrawn (consent_revoked); the text is discarded
errorcode, scope, retry_after, limitThe conversation is blocked or at its cap; with conversation_limit a notice text and handoff follow
tooldetails of the tool callA tool call by the assistant
model_switchreason, from, toInternal switch during the reply, of no relevance to your integration
endstate, message_id, duration_ms and moreLast event; state is done, aborted, fallback, revoked, live or blocked

With conversation_limit the notice text in English reads: “This conversation has reached its agreed length. I am handing it over to a person – please leave your question together with a way to reach you, or start a new conversation.” If the conversation is blocked for another reason, error is followed by the assistant's fallback reply and end with blocked.

chat.mjs javascript

import { Klient } from './klient.mjs';

const klient = new Klient('https://app.xicbot.de', process.env.XICBOT_KEY);
let antwort = '';

await klient.postChat({ assistant_id: 'ASSISTANT_ID', text: 'When are you open?' }, (art, daten) => {
	if (art === 'start') console.log('Conversation', daten.conversation_id);
	else if (art === 'text') antwort += daten.t;
	else if (art === 'redaction') antwort = daten.text;
	else if (art === 'error') console.error('Blocked:', daten.code);
	else if (art === 'end') console.log(antwort, daten.state);
	// any other type: skip
});

anfrage.py python

import os
from klient import Klient

klient = Klient('https://app.xicbot.de', os.environ['XICBOT_KEY'])
ergebnis = klient.post_leads({
    'subject': 'Call back about the quote',
    'email': 'customer@example.com',
    'external_id': 'crm-4711',
})
# 201 the first time, 200 with duplicate_prevented on a repeat
print(ergebnis['lead']['id'], ergebnis['duplicate_prevented'])

The structure of every operation is described in Integration endpoints; how conversations appear in the app is covered in Conversations.

Verifying webhooks

A webhook sends events from your account to an address on your system. You set it up on the same page as the keys, under Administration › Interfaces in the Webhooks section: “Every delivery carries a signature in the X-XICBOT-Signature header. Failed deliveries are retried.”

  1. Step 1

    Enter the address

    Under Target address enter an address of at most 2048 characters. It has to point to the public internet; otherwise the page shows “This address is not permitted as a target.”

  2. Step 2

    Choose events

    Under Events tick at least one. Create webhook stays disabled until the address and one event are set.

  3. Step 3

    Copy the secret

    After creation the page shows Your signing secret once: whsec_ followed by 48 characters, with the note “Use it to verify the signature of an incoming delivery.” Use Copy secret to take it over into your system.

Each delivery is a POST with a JSON body of four fields: event (the event type), at (time of the event in ISO 8601 format, the same in every retry), tenant (your account ID) and data (the event payload). These headers come with it:

HeaderContent
X-XICBOT-EventThe event type, for example lead.created
X-XICBOT-DeliveryA UUID per event and receiver; every retry carries the same one
X-XICBOT-AttemptNumber of the attempt, starting at 1
X-XICBOT-Signaturet=<Unix time>,v1=<HMAC-SHA256 in hex>
User-AgentXICBOT-Webhook/1

Checking the signature

  1. Step 1

    Read the raw body

    The body is signed exactly as it arrives. Read it before any JSON processing; a body that is parsed and serialised again becomes a different string with a different signature.

  2. Step 2

    Split the header

    The X-XICBOT-Signature header holds t and v1, separated by a comma. If either is missing or t contains anything other than digits, reject the delivery.

  3. Step 3

    Check the age

    If t differs from your clock by more than 300 seconds, the kit rejects the delivery. The value is the hoechstalter parameter; 0 turns the check off, which lets a captured delivery be replayed any number of times.

  4. Step 4

    Compute the signature

    HMAC-SHA256 over t, a dot and the raw body, with the signing secret as key, as a hex string.

  5. Step 5

    Compare in constant time

    The kit compares with timingSafeEqual (Node), hash_equals (PHP) or hmac.compare_digest (Python). A comparison that stops early reveals through its running time how many characters already match.

LanguageCallResult
NodesignaturPruefen(koerper, kopf, geheimnis, hoechstalter = 300)true or false; koerper as string or Buffer
PHPxicbot_signatur_pruefen($koerper, $kopf, $geheimnis, $hoechstalter = 300)true or false
Pythonsignatur_pruefen(koerper, kopf, geheimnis, hoechstalter=300)True or False, also for a body that is not valid UTF-8; koerper as bytes or str

webhook.php php

<?php
require_once __DIR__.'/signatur.php';

$koerper = file_get_contents('php://input');
$kopf = $_SERVER['HTTP_X_XICBOT_SIGNATURE'] ?? '';
$geheimnis = (string) getenv('XICBOT_WEBHOOK_SECRET');

if (! xicbot_signatur_pruefen($koerper, $kopf, $geheimnis)) {
    http_response_code(401);
    exit;
}

$sendung = json_decode($koerper, true);
// evaluate $sendung['event'] and $sendung['data']
http_response_code(204);

Delivery and retries

  • XICBOT waits up to 8 seconds for your reply. Any status from 200 to 299 counts as delivered; XICBOT does not follow redirects.
  • A delivery goes to every webhook that is switched on and subscribed to the event.
  • The address is checked when the webhook is created and again before each delivery.
  • If an attempt fails, there are up to three attempts in total, usually after 30 and after 120 seconds. Each retry carries the same X-XICBOT-Delivery and the same at, a higher X-XICBOT-Attempt and a newly computed signature with a current t.
  • Consecutive failures counts every failed attempt, including a delivery that the address check before sending already stops, and drops to 0 after a successful delivery. A signing secret that could not be read (secret_unreadable) does not count. At 20, XICBOT switches the webhook off and the row shows disabled. When you switch it back on, the count starts again at 0.
  • The button in the row names the action: Turn off for a running webhook, Turn on for one that is switched off.
  • Deliveries shows the last 50 attempts with Time, Events, Attempt, Status and Duration in milliseconds. Delete asks first: “Delete this webhook? Deliveries to this address stop immediately, and the signing secret cannot be restored.” The webhook address is shown below. The webhook is only deleted with Delete in the dialog; Cancel keeps it.

The Status column shows the status of your reply or one of these reasons:

ReasonShown as
redirect_not_followedThe target redirected. Redirects are not followed – please enter the final address.
secret_unreadableThe signing secret could not be read.
webhook_inactiveThe receiver is switched off.
webhook_deletedThe receiver has been deleted.
url_unreadableThe address cannot be read.
scheme_not_allowedThis address type is not supported.
name_unresolvableThe host name of the address cannot be resolved.
target_not_allowedThis target is not allowed, for example an internal address.

Events

EventIn the app
conversation.startedConversation started
conversation.endedConversation ended
handoff.triggeredHandover triggered
lead.createdEnquiry created
appointment.requestedAppointment requested
appointment.confirmedAppointment confirmed
knowledge.indexedKnowledge source indexed
knowledge.failedKnowledge source failed
gap.detectedKnowledge gap detected
budget.exhaustedBudget exhausted

RUECKRUF_EREIGNISSE in the kit holds the same ten types. Keys and webhooks from the administration side are covered in API keys and webhooks.

When XICBOT calls your system

An assistant can call your system as a tool. Tools are set up per assistant under Triggers › Tools: with the Type Own interface for a free-form call, or with a type that speaks a fixed format, for example Read free slots. Approval, minimum role and required details are covered in Create and approve tools.

FieldRule
Keylower-case letter first, then lower-case letters, digits and underscore; 3 to 64 characters, unique per assistant
Labelrequired, up to 120 characters
When should the assistant use it?required, up to 600 characters
Interface addresshttp:// or https://, on the public internet; checked on saving and before each call. Own interface and the types with a fixed format require it: without an address the tool cannot be saved, and the field shows “This type talks to an external system. Without an interface address it cannot work.” If the service rejects the address, the sentence at the field gives the reason, for example “The host name of this address cannot be resolved. Please check the spelling.”; all sentences are listed under Which addresses are allowed.
Access tokenSent as authorization: Bearer <token>; an empty field leaves a stored token unchanged
Input fieldsOnly with Own interface: up to 20 fields; name starts with a lower-case letter, then a–z, 0–9 and _, up to 40 characters
Typestring, integer, number or boolean; anything else becomes string
Description of a fieldup to 200 characters

XICBOT does not accept fields named tenant_id, mandant, mandant_id or konto_id: a tool with such a field cannot be saved. Your system receives only the fields declared in the tool; anything else the assistant sends is dropped.

Own interface

With the Own interface type, XICBOT sends a POST with content-type: application/json and accept: application/json to the stored address. The body has three fields: tool (the tool's Key), input (the declared fields) and conversation_id. Strings in input are cut to 2000 characters, lists to 50 entries and nesting to three levels. No idempotency-key header is sent with this call.

anfrage.json json

{
  "tool": "delivery_time",
  "input": { "postcode": "10115" },
  "conversation_id": "9d1c…"
}

XICBOT passes the status of your reply to the assistant as status. If the reply is a JSON object or a JSON array, it arrives as data; any other reply is passed on as text, cut to 2000 characters. You decide which fields your JSON carries.

Types with a fixed format

The other types that talk to an external system send a fixed envelope with seven fields and expect a fixed reply. Writing operations also carry the idempotency-key header: 64 hex characters derived from conversation, tool and input. A repeated call with the same input in the same conversation carries the same value, so your system can recognise it as a repeat. Reading operations do not carry it.

FieldContentExample Read free slots
adapterID of the typecalendar_availability
domainDomainkalender
operationKind of operation: read or writeread
actionOperationavailability.list
toolthe tool's Keyas entered
conversation_idID of the conversation–
inputThe fields of the typefrom (required), to, kind, duration_min

antwort.json json

{
  "ok": true,
  "data": {
    "slots": ["2026-10-06T09:00", "2026-10-06T10:30"],
    "timezone": "Europe/Berlin",
    "note": "Saturdays mornings only"
  }
}

From data XICBOT takes only the result fields of the type, for Read free slots that is slots, timezone and note. Strings are cut to 600 characters, lists to 20 entries and nesting to two levels. To decline, your system replies with "ok": false and a reason in error; XICBOT keeps up to 200 characters of it. If ok is missing, the reply counts as a breach of the format.

Call limits

LimitValue
Waiting time for the reply8 seconds by default
Connection setupat most 5 seconds
Size of the replyat most 64 KB, otherwise discarded
Redirectsnot followed
Successful replystatus 200 to 299
Tool calls per replyat most 5

A call that succeeds is recorded in the history as executed. If the waiting time runs out it shows as timed out; any other error shows as failed with the message, cut to 500 characters. XICBOT records the duration of each call in milliseconds. A redirect also ends as failed. XICBOT does not retry a failed call on its own. These messages can appear:

Message (German original)Cause
Für dieses Werkzeug ist keine gültige Adresse hinterlegt.address missing or not starting with http:// or https://
Die hinterlegte Adresse zeigt nicht ins offene Netz.check right before the call
Das Werkzeug hat innerhalb von 8 Sekunden nicht geantwortet.waiting time expired
Das Werkzeug war nicht erreichbar.connection failed
Das Werkzeug hat mehr als 64 KB geliefert. Die Antwort wurde verworfen.reply too large
Das Werkzeug hat weitergeleitet (Status 302). Einer Weiterleitung folgt es nicht.status 300 to 399, here with 302 as example
Das Werkzeug hat mit Status 500 geantwortet.other status outside 200 to 299, here 500
Das angebundene System hat nicht nach dem Anbindungsvertrag geantwortet.fixed-format type: no JSON or no ok field
Das angebundene System hat den Vorgang abgelehnt: <Grund>fixed-format type: ok is not true
Dieses Werkzeug gibt es für diesen Assistenten nicht.the assistant calls an unknown Key
Dieses Werkzeug ist für diesen Zugang nicht freigegeben.the role in the conversation is below the minimum role
Der Deckel von 5 Werkzeugaufrufen je Antwort ist erreicht.sixth call within one reply

Whether a call runs straight away or only after the visitor confirms it is set by Approval: without asking or with confirmation. Own interface is preset to with confirmation. A reading tool set to without asking runs straight away, as does the query for free slots with Book appointment; XICBOT stores a writing tool with with confirmation whatever was chosen. If a required input field is missing, the call ends as failed before your system is contacted. Details are in Create and approve tools.

Frequent questions

Why does the signature check fail although the secret is right?

Usually the body was parsed as JSON and serialised again before the check instead of using the raw body. Other causes are the secret of a different webhook, a server clock that is more than 300 seconds off, or a proxy that alters the body.

How do I recognise that a webhook delivery was retried?

By the X-XICBOT-Attempt header, which is greater than 1 from the second attempt on. X-XICBOT-Delivery keeps the same UUID in every retry, so you can recognise a delivery you have already processed. For enquiries the content of data, such as the id, also helps.

Why do I get 401 even though I send a key?

key_missing means the X-Api-Key header is absent or its value does not start with xbot_. invalid_key means the key is unknown, revoked or expired. Whether a key has been revoked or has expired is shown in the Status column of the list under Interfaces.

Can I continue a widget conversation through the API?

No. conversation_id only continues a conversation that the same assistant started through the API; XICBOT answers any other with 404 and not_found.

My system needs more than 8 seconds. What happens?

The call ends as timed out and the assistant receives no result. Reply quickly, for example with a reference number, and do the long work afterwards.

Something still unclear?

Tell us which page and which step you mean. We reply personally.

Enquiry in three steps

  1. 1. Topic
  2. 2. Your case
  3. 3. Contact

What is this about?

One click is enough, everything else is optional.

Tell us briefly about your case

Everything in this step is optional. It helps us reply with something concrete straight away instead of asking back.

Enquiries per month, roughly (optional)
When should it start? (optional)
How can we reach you?

Name and email address are enough. We reply personally.

We use your details to handle your enquiry. More on this in the privacy policy.