Skip to content
XICBOT

Settings

Deutsch
Documentation · Operations and security

Availability, status and alerts

Public status and changelog endpoints without sign-in, headers and error responses, the operator's operations area, and how to spot a takeover of your account.

In plain language

The service checks its important parts by itself. These include the database, the storage and the mail path. A short status can be read without signing in. A more detailed status is in the operations area. The page also explains the public change log. It shows how you can tell that your account was taken over for support.

Last updated

All documentation topics

XICBOT checks the state of its load-bearing parts on its own: database, cache, file storage, queue, recurring runs, background service, mail path, the connection used to generate answers, and the database schema. You get the result in two ways: briefly and without signing in through the public status endpoint, and in detail in the operations area. This page covers both, plus the public changelog, the headers and error responses of the API, and how to tell that your account has been taken over for support. *Operator* here means whoever runs the platform, not you as the owner of your website.

Public status endpoint

The status endpoint works without signing in, because an outage is exactly when you want to look things up and signing in may be failing. Its answer is deliberately terse: it says whether each part is working and nothing else. Error texts, table names, host names and queue figures stay in the operations area.

GET /api/v1/public/status

Returns the overall state and the state of each of the nine parts. A request that is not served from the cache triggers a real write-and-read probe.

Authentication
None
Rate limit
30 requests per minute per origin (IPv4 per address, IPv6 per /64), one counter shared with the changelog, the demo lookup and the accessibility statement

curl bash

curl -s -w '\nHTTP %{http_code}\n' https://app.xicbot.de/api/v1/public/status

antwort.json json

{
  "state": "degraded",
  "measured": true,
  "parts": [
    { "name": "database", "state": "operational" },
    { "name": "cache", "state": "operational" },
    { "name": "storage", "state": "operational" },
    { "name": "queue", "state": "operational" },
    { "name": "schedule", "state": "operational" },
    { "name": "daemon", "state": "operational" },
    { "name": "mail", "state": "degraded" },
    { "name": "gateway", "state": "operational" },
    { "name": "schema", "state": "operational" }
  ],
  "time": "2026-09-28T08:15:02+00:00"
}
HTTP 503

The example shows a failing mail path: every part was measured, one is not healthy, so the overall state is degraded and the status code is 503.

Response fields

FieldContent
stateOverall state: operational, degraded or unknown
measuredtrue if every part could be measured, otherwise false
partsList of parts, each with name and state
timeTime of the response in ISO 8601, UTC

States and status code

ValueOverallPer partStatus code
operationalEvery part was measured and found healthy.Measured and healthy200
degradedAll parts measured, at least one unhealthy.Measured but unhealthy503
unknownAt least one part could not be measured.Not measured503

The nine parts

PartWhat is checkedHealthy when
databaseA probe row is written, read back, compared and deleted.the value read matches the value written
cacheA random value is stored for 60 seconds, read and removed.the value read matches the value stored
storageA probe file is written to file storage, read and deleted.the content read matches the content written
queuePending, running and failed jobs, plus the age of the oldest pending jobthe oldest pending job has waited less than 900 seconds and fewer than 20 jobs failed in the last hour
scheduleThe heartbeats of the recurring runs, each with its own deadlineno run is overdue and none failed on its last attempt
daemonThe heartbeat of the background service and how its lanes are being servedthe heartbeat is fresh and no lane has an open job left unserved for 900 seconds or more
mailWhether a sending route is configured and ready, plus failed deliveries in the last hourthe route is ready and fewer than 10 deliveries failed in the last hour
gatewayThe connection to the service that generates the assistants' answers: access key present, connection accepted. No answer is requested for this.the key is present and the remote end is reachable
schemaWhether the expected database tables, columns and indexes existnone of them is missing

Heartbeats of the background service count towards daemon, not schedule. If the background service has never written a heartbeat, that is a finding rather than a missing measurement, so the part shows degraded, not unknown. The schema check catches a migration that has not run before a visitor stumbles into it.

Caching and probe failure

The measurement is cached for 20 seconds, so requests closer together get the same result. time is when the response was produced, not when the measurement was taken. The cache itself lives in the database; if the database is down, the probe runs without the cache instead of losing the answer. If the probe fails as a whole, the endpoint answers with unknown, measured: false and a single part called total.

Connecting your own monitoring

  1. Step 1

    Request the endpoint

    Call GET https://app.xicbot.de/api/v1/public/status without signing in and without a key.

  2. Step 2

    Check the status code

    200 means operational. 503 means degraded or not measured.

  3. Step 3

    On 503, read the parts

    Parts marked degraded are failing; parts marked unknown were not measured.

  4. Step 4

    Pick an interval

    Polling more than once every 20 seconds yields no new measurement. The counter of 30 requests per minute is shared by the status endpoint, the changelog, the demo lookup and the accessibility statement; once it is used up, the API answers with 429.

Changelog

The changelog is kept as a file next to the code, not in the database: an entry describes the version it shipped with and is not changed afterwards. Like the status endpoint, it can be read without signing in.

GET /api/v1/public/changelog

Returns the changelog entries, sorted by date descending and, for equal dates, by version descending.

Authentication
None
Rate limit
30 requests per minute per origin, one counter shared with the status endpoint, the demo lookup and the accessibility statement (IPv4 per address, IPv6 per /64)
FieldContent
measuredtrue if the file could be read
reasonWhy reading failed, otherwise null
versionVersion of the newest entry, or null
entriesEntries with version, date, kind, title and points

kind is one of feature, fix, security or note; any other value is returned as note. points holds the individual points of an entry as a list of strings, with empty points dropped. An entry without a version, date or title is skipped.

"Not measured" is not a result

"The value is 0" and "the value was never determined" look identical in a column of numbers and mean opposite things. XICBOT therefore keeps them apart: a part whose measurement fails carries measured: false, value: null and a reason in reason of up to 300 characters. It does not count as healthy, and the overall result becomes unknown.

In the operations area such a part shows as Not measured, with the reason below it. If the state response cannot be read at all, the page shows the note This value could not be determined and is therefore not a result. instead of the parts.

Headers and error responses

Every response the API itself produces carries the X-Konfigurationsstand header, error responses included. Its value is a hash over the configuration in effect, not its content. Two responses with the same value come from the same state; if the value changes, a different state is answering. A single request therefore tells you whether a change has taken effect.

StatusBodyCause
301–Request over HTTP, whatever the method: the web server redirects to HTTPS.
403{"error":"https_required"}Only if an unencrypted request with a method other than GET or HEAD reaches the application itself: it is refused rather than redirected.
404{"error":"route_unknown"}No such address under /api/.
405{"error":"method_not_allowed","allowed":[…]}The address exists, but not for this method; allowed lists the permitted ones.
429Error response with the Retry-After headerA throttle is exhausted; for the status endpoint and the changelog after 30 requests per minute per origin.
500 and abovemessage: ServerfehlerInternal error; exception, file, line and stack trace are stripped from the response.
503Status endpoint: state with measured and parts; changelog: measured: false and reasonStatus endpoint unhealthy or not measured, changelog unreadable

Responses served over HTTPS carry Strict-Transport-Security: max-age=31536000; includeSubDomains, so the browser uses encrypted connections only, for the address and its subdomains, for one year. preload is deliberately left out. The application pages and the responses under /api/ also send these headers:

HeaderValueEffect
X-Content-Type-OptionsnosniffThe browser does not guess content types.
X-Frame-OptionsDENYThe browser does not embed the application in any frame.
Referrer-Policystrict-origin-when-cross-origin on the pages, no-referrer under /api/Other sites learn only the origin of the pages, not the path; API responses pass on no referrer at all.
X-Robots-Tagnoindex, nofollowSearch engines are told not to index the application and not to follow its links.

The operator's operations area

The Operations area lives at https://app.xicbot.de/betrieb and appears in the navigation under Operator. Only accounts carrying the operator flag can open it. That flag is a separate attribute of the user, not a role: owners and admins of a tenant do not get in, since they would otherwise learn about other tenants. The Operator group also holds the Blog preview: it shows scheduled posts of the XICBOT website before they appear and follows the same access rules. As a customer you will see neither area. The operations area is described here so you know what the operator can see about your account and what they can do with it. You can see your quotas under Plans and quotas. The current state of the platform comes from the public status endpoint described above; the status page requests this endpoint in the browser when it opens and shows the state with the time of measurement; without an answer it says "not measured". Below that it explains what is monitored.

Method and pathContent
GET /api/v1/admin/healthMeasurement of all parts with values and duration in duration_ms; 200 when healthy, otherwise 503
GET /api/v1/admin/heartbeatsHeartbeats of the recurring runs
GET /api/v1/admin/alertsOpen notices, including seen ones with all=1; up to 200
POST /api/v1/admin/alerts/{id}/acknowledgeMark a notice as seen
GET /api/v1/admin/jobsQueue jobs, up to 100, filterable by status
POST /api/v1/admin/jobs/{id}/retryReset a failed job to pending with its attempts at 0; for any other state the API answers 409 not_failed
GET /api/v1/admin/mail-deliveriesDelivery log across all tenants
GET /api/v1/admin/plansPlans with their resolved features
GET /api/v1/admin/tenantsTenants, most recently created first, 25 per page, up to 100 with per_page; the response states total, page, pages and per_page. Without status, deleted tenants are left out; status (active, paused, suspended, deleted or all) and plan narrow the list, search matches name, slug and billing e-mail literally. GET /api/v1/admin/tenants/{id} for a single one, including its people with second_factor
PUT /api/v1/admin/tenants/{id}Change a tenant's plan, status, budget and limits; 409 tenant_deleted for a deleted tenant
POST /api/v1/admin/tenants/{id}/impersonateTake over a tenant's account
GET /api/v1/admin/demosDemos that still exist, expired ones included, newest first, up to 100; per demo the website (host), the prospect's address (contact), the deadline (expires_at, expired), the state of the import (knowledge) and the embed line (snippet), plus active_max and lifetime_hours
POST /api/v1/admin/demosCreate a demo from url, optionally with the prospect's email and language (de or en); 201 for a new one, 200 with existing: true if one is already running for the same website. The per-connection cap of the public endpoint does not apply here, the maximum number of simultaneous demos does (503 demo_capacity)
POST /api/v1/admin/users/{id}/second-factor/resetReset a customer account's two-factor authentication; reason with 10 to 500 characters is required. The response gives sessions_ended and mail_queued; 403 operator_account for operator accounts, 409 no_second_factor if none is set up
GET /api/v1/admin/audit-logAction log, newest first, up to 200 entries; tenant narrows it to one tenant
GET /api/v1/admin/integrityChecks whether the deletion catalogue, permission fields and plan gates fit together; anything that could not be measured carries measured: false and a reason

State

State lists the nine parts as Operational, Degraded or Not measured; Measure again triggers a fresh measurement. Unlike the public endpoint, the area's API returns measured values for each part. For a degraded part the page names the cause, such as missing tables, unserved lanes or failing runs; for an unmeasured part it shows the reason. The page reads the response even when it comes with a 503. If the page fails to load, the error message appears at the top, and instead of the sections only the button Load again is shown, which repeats the loading.

PartValues (selection)
queuepending, running, failed, failed_1h, oldest_pending_s
scheduleentries, failed, overdue, last_run_failed
daemonlast_run_ago_s, deadline_s, workers, lanes, stalled_lanes
mailfailed_1h, sent_24h, note
gatewaykey, reachable, connect_ms, note
schemachecked, missing

For schedule, failed combines both findings, while overdue and last_run_failed tell them apart. A run that is missing and a run that keeps failing call for different fixes.

Recurring runs

Every recurring run writes a heartbeat. For each run, the Recurring runs table shows Last run, Last success, Deadline and the state Overdue, Last run failed or Operational. Which runs exist, the deadline of each and the notices a failed or missing run produces are covered under Heartbeat and notices.

Notices

Problems are collected as notices under Notices. Each notice has a key made of its source and cause. When the same problem occurs again, no new row appears: the count goes up, the last-seen time is updated, and a notice already marked as seen becomes unseen again. Titles are cut to 200 characters, texts to 4000.

ValueShown asOrder
criticalCriticalfirst
warningWarningnext
infoInfolast

Within one severity, the most recently seen notices come first. An unknown severity is stored as warning. The source is shown by its label: Catalogue, Handover, Knowledge, Mail, Maintenance, Queue, Quota, Schedule, Database schema, Privacy or Webhook.

NoticeSourceSeverity
A recurring run failed.schedulecritical
A recurring run is overdue.schedulecritical
Jobs were ended unexecuted after 7 days.queuewarning
A job failed for good after its last attempt.queuecritical
An e-mail was not delivered.mailwarning
Tables, columns or indexes are missing.schemacritical
A database schema error (1054 missing column, 1146 missing table, 1062 duplicate entry, 1091 missing index)schemacritical
An account objected to a version of the sub-processor list; one notice per account and version, with the reason. The objection itself is listed in the tenant view under Objections to subprocessors.privacywarning

The list shows open notices; with none open it reads No open notices. Mark as seen files a notice away, which is recorded in the action log as message.seen.

Queue

The Queue lists jobs with Kind, State and Attempts. For a failed job, Try again puts it back to pending and resets its attempt counter to 0; the action is logged as job.retry.

  • If a job's payload was reduced to references after it failed, it cannot be retried: the API answers 409 payload_reduced and the page shows Cannot be retried: the payload was reduced after the job failed. The action then has to be triggered again.
  • If a job is no longer failed because someone has requeued it in the meantime or it is already running, the API answers 409 not_failed. The page then reloads the list and shows This job cannot be retried: it is no longer failed but has already been requeued or is running.
  • Jobs waiting or running for more than 7 days are ended without being executed, and a warning from the Queue source is raised.
  • Failed jobs remain visible until the clean-up after 14 days.

How jobs are created and processed from your side is covered in Background jobs and Schedules.

Delivery log

The Delivery log covers the messages of all tenants. A row appears as soon as a message is triggered, even when no delivery route is set up and it therefore never goes out. Recipient addresses are shortened to the first letter and the domain, for example m***@example.com: the domain is enough to tell whether a remote server is rejecting messages. Addresses are shortened the same way in the reason for a failure, in the notice about an undelivered e-mail and in the error of a failed mail job; a remote server often names the address in its rejection.

StateShown as
queuedQueued
sentDelivered
failedFailed

Besides Recipient, the list shows Tenant, Delivered at, Attempts and Reference. Only failed rows carry an error reason, such as ungültige Empfängeradresse (invalid recipient address) or unbekannte Vorlage (unknown template). The API filters by status, template and tenant and returns 25 rows per page, up to 100 with per_page; the response states total, page, pages and per_page.

Tenants and limits

Under Tenants the operator sees, per tenant, Status, Plan, Users, Assistants (active/total), Conversations and Usage this month, most recently created first and 25 per page. Above the list are the range shown and the total number of matches; with more than one page, Back and Next below it turn the pages. The field Search by name, slug or billing e-mail searches these three details literally, the Status filter starts at all except deleted, and the Plan filter narrows the list to one plan. Take over account appears only for active tenants; for the others the row names the status. The name leads to the tenant's page. Under Master data it gives status, plan, slug, creation, billing e-mail, VAT ID, the acceptance of the data processing agreement, the stored values for data region and model route and the Retention periods per type of object as they take effect: without a number of their own, test and API conversations follow the period for all conversations. For a deleted tenant it states instead that only a shell with its audit log remains, which the maintenance run removes once its period has expired. Under Quota it shows usage this month against the budget, the limits in force and the deviations from the plan. Limits, Users and Assistants (active/total) follow below. For assistants only operational facts such as embedding and last seen are shown; the system instruction stays with the customer.

LimitFieldRange
Context window (messages)history_window2 to 100
Message length (characters)max_input_chars200 to 4000
Questions per conversation (0 = none)max_messages_per_conversation0 to 1000, default 60, 0 means no cap
Questions per visitor/minutevisitor_rate_limit_per_min0 to 1000, default 10
Questions per visitor/dayvisitor_rate_limit_per_day0 to 100000, default 200

Zero switches the per-visitor cap and the per-conversation cap off. Save limits on the tenant's page applies the values. The response to GET /api/v1/admin/tenants and the single view GET /api/v1/admin/tenants/{id} return all five limits with their current values. For the message length both of them, and the response to PUT /api/v1/admin/tenants/{id}, give the effective value: a stored value above 4000 takes effect, and is shown there, as 4000; with no stored value they also show 4000. Through the API the operator can also set the plan (plan), status (active, paused, suspended) and monthly_token_budget (0 to 1000000000). A deleted tenant can no longer be changed: PUT /api/v1/admin/tenants/{id} then answers 409 tenant_deleted, and its page shows no limit fields. Each change is logged as tenant.update with the old and new values; for the message length the entry keeps the stored value. What the plans include is explained in Plans and quotas, prices are on the pricing page.

Resetting two-factor authentication

On the tenant's page, the number next to Users is a toggle: it expands the tenant's people with Name, Email address, Role, Two-factor authentication (Yes or No) and Action. The count and the list include every member of the tenant, including people who are currently working in another tenant; Role gives their role in this tenant. If someone has lost the only device for two-factor authentication, it can be reset here. For customer accounts with two-factor authentication set up, Action holds the button Reset two-factor authentication. It opens the question Remove this person's authenticator code and security keys and end all of their sessions? with the field Reason (recorded in the operator log), at least 10 and at most 500 characters, and the buttons Reset and Cancel. Operator accounts show Operator account instead of the button; the API refuses them with 403 operator_account.

Reset removes the person's authenticator code and all security keys and ends all of their sessions, including a running takeover. As with End takeover, its end is recorded as impersonation.end in the Action log and in the tenant's Audit log, and sessions_ended in the response includes it. Afterwards the page shows Two-factor authentication has been reset. A security notice to the account's email address is on its way. If the notice could not be queued, it shows Two-factor authentication has been reset, but the security notice could not be queued. Please notify the person yourself. instead. The reset is recorded with its reason as user.second_factor_reset in the Action log and, as Two-factor authentication reset by the operator, in the Audit log of the tenant the person is currently working in. If either entry cannot be written, two-factor authentication stays in place; the API responds with 500 and not_logged, and the page shows Not saved: the entry in the audit log could not be written. Please try again. If the person no longer has two-factor authentication, the row shows This person no longer has two-factor authentication set up. How two-factor authentication works for the person themselves is described under Account security.

Account takeover

For support, the operator can switch into a tenant's account. They enter a Reason for the takeover of up to 200 characters and choose Take over account. The button appears only for active tenants. The takeover targets the highest-ranking account currently working in this tenant, in the order owner, admin, editor, viewer; a member who is currently working in another tenant is not considered. If no account is currently working in the tenant, the API refuses with 422 tenant_without_user. How long a takeover lasts, what is blocked from within it and how it is logged is described under Takeover by the operator.

How to spot a takeover

You can spot and end a running takeover in the device list of the login that was taken over, under Signed-in devices, on the row Takeover by the operator. The details are under Takeover by the operator, the device list under Account security.

Demos on request

The operator sets up a demo when a prospect asks for one through the enquiry form. Under Demos they enter the Website address, optionally the Email address of the prospect and the Language of the assistant, and choose Create demo. This creates a separate tenant with an assistant that answers only from this website and can only be embedded on it; the website is read in the background. The list below shows per demo the Website, Prospect, Runs until, Knowledge with the state of the import and the Embed line that the operator sends to the prospect; nothing is sent automatically. A demo runs for 72 hours, after which its assistant no longer answers, and a week later the maintenance run removes it. Every newly created demo is recorded as demo.create in the action log. The public endpoint POST /api/v1/public/demo still exists, but the website does not offer it.

Action log

The Action log records what the operator did in the area: changes to plan, status, budget and limits (tenant.update), retried jobs (job.retry), notices marked as seen (message.seen), the start of takeovers (impersonation.start), their end (impersonation.end), two-factor resets (user.second_factor_reset) and created demos (demo.create). The end of a takeover is usually recorded when it ends via End takeover, by signing out during the takeover, by the person themselves under Signed-in devices, or because all sessions of the account end: after a new password is set via the link, when two-factor authentication is reset, when the person is removed from the team or when the account is deleted, including an expired demo. The end is also recorded there when the account taken over switches to another tenant itself. A takeover that expires on its own after four hours leaves no end entry; if writing the entry fails when it ends, the takeover still ends and the failure only appears in the system error report. Who shows the address of the operator who provided the support; if the customer side ended the takeover, Ended by the customer appears below it, and if it ended because an expired demo was deleted, Ended when the expired demo was deleted. If an account other than that of the supporting operator triggered the end, for example the person themselves, whoever removed them from the team or a second operator resetting two-factor authentication, Triggered by also appears with that account's address. If the takeover ended with a new password via the link, a switch to another tenant or removal from the team, a further line names the cause, for example Cause: the account was removed from the team. The page shows the latest 50 entries and reads No action logged. while there are none. The API returns up to 200 entries, newest first.

Further reading

Frequent questions

Why does the status endpoint return 503 while my assistant is still answering?

The endpoint returns 200 only in the operational state. If a single part is failing, the mail path for instance, or could not be measured, the code is 503 even though conversations keep working. parts tells you which part it is.

How often may I poll the status endpoint?

Up to 30 requests per minute per origin. The status endpoint shares this counter with the changelog, the demo lookup and the accessibility statement. Since the result is cached for 20 seconds, polling more often does not give you a new measurement.

Can I open the operations area with my owner account?

No. Access depends on a separate operator flag, not on your role. A customer account gets 403 not_operator.

How can I tell that the operator has taken over my account?

In the account taken over, the highest-ranking one currently working in your tenant, Signed-in devices then shows a row called Takeover by the operator. End stops it; at the latest it expires on its own after four hours.

Why are recipient addresses shortened in the delivery log?

The list spans all tenants, and the recipients of other tenants are none of the operator's business. The domain is enough to see whether a remote server is rejecting messages.

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.