ACP · Integration

SchnellstartQuickstart

Von null auf eine beantwortete Frage — in sechs Schritten. From nothing to an answered question — in six steps.

Jeder Aufruf unten ist gegen die laufende Plattform geprüft. Ersetzen Sie $ACP durch Ihre Instanz und $KEY durch Ihren Schlüssel. Es gibt keine SDK-Pflicht: die Schnittstelle ist HTTP und JSON. Every call below is checked against the running platform. Replace $ACP with your instance and $KEY with your key. No SDK is required: the interface is HTTP and JSON.

01 · Zwei Schlüssel, zwei ZweckeTwo keys, two purposes

Wir stellen sie aus und übergeben sie Ihnen; es gibt bewusst keinen Endpunkt, der Schlüssel erzeugt. Sagen Sie uns Ihre Mandanten-Kennung und — für das Widget — die Domains, auf denen es laufen soll. We issue them and hand them over; there is deliberately no endpoint that mints keys. Tell us your tenant id and — for the widget — the domains it will run on.

SchlüsselKey Wo er lebtWhere it lives Was er darfWhat it grants
acp_sk_… Ihr Server, Ihr Secret-Storeyour server, your secret store Lesen und Schreiben im ganzen Mandantenread and write across the whole tenant
acp_pk_… Ihre öffentliche Webseiteyour public web page nur: ein Gespräch von einer erlaubten Domain beginnenonly: start a chat from an allow-listed domain

Die eine Regel: acp_sk_ gehört niemals in eine Webseite. Alles auf einer Seite ist lesbar. Ein dort eingefügter API-Schlüssel ist ein veröffentlichter Schlüssel — und er gilt für Ihren gesamten Mandanten. The one rule: acp_sk_ never belongs in a web page. Everything on a page is readable. An API key pasted there is a published credential — and it covers your entire tenant.

Widerruf wirkt sofort und ohne Neustart. Melden Sie einen verlorenen Schlüssel — wir sperren ihn, der nächste Aufruf wird abgewiesen. Revocation is immediate and needs no restart. Report a lost key — we revoke it and the next request is refused.

02 · Prüfen, wer Sie sindProve who you are

Jede Route leitet den Mandanten aus dem Schlüssel ab. Sie können keinen fremden Mandanten benennen — es gibt keinen Parameter dafür. Every route derives the tenant from the key. You cannot name someone else's tenant — there is no parameter for it.

curl -s $ACP/v1/tenant -H "Authorization: Bearer $KEY"

{"tenant_id":"acme","key_id":"b40651827aa99a04","scopes":["read"],"region":"eu-central-1"}

/v1/health ist der einzige Endpunkt ohne Authentisierung — gedacht für Ihren Load Balancer. /v1/health is the only endpoint without authentication — meant for your load balancer.

03 · Wissen einspielenLoad your knowledge

Alles, was Sie schreiben, wird ein Entwurf. Veröffentlichen bleibt eine menschliche Handlung in der Konsole — eine Schnittstelle, die im Namen Ihres Unternehmens sprechen lässt, ohne dass jemand zugestimmt hat, wäre keine Funktion. Everything you write arrives as a draft. Publishing stays a human action in the console — an API that lets anything speak for your company without a person agreeing to it would not be a feature.

curl -s $ACP/v1/knowledge -X POST \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"title":"Terminal offline",
       "body":"Trennen Sie das Terminal 30 Sekunden vom Strom …",
       "category":"hardware","language":"de",
       "summary":"Erste Schritte, wenn ein Kartenterminal offline geht"}'

Abrufen, wie der Agent es tut — nur veröffentlichtes, kundentaugliches Wissen, nach Sprache: Retrieve it the way the agent does — published, customer-safe knowledge only, scoped by language:

curl -s "$ACP/v1/knowledge-search?q=terminal+offline&language=de&limit=5" \
  -H "Authorization: Bearer $KEY"

Ein frisch angelegter Entwurf erscheint hier nicht. Das ist kein Fehler, sondern dieselbe Zusage: unveröffentlicht heißt unerreichbar. A freshly created draft does not appear here. That is not a bug but the same promise: unpublished means unreachable.

04 · Ein Gespräch führenHave a conversation

Die Gesprächs-Kennung wählen Sie. Derselbe Aufruf mit derselben Kennung setzt das Gespräch fort; der Verlauf ist der Kontext. You choose the conversation id. The same call with the same id continues the conversation; the transcript is the context.

curl -s $ACP/v1/conversations/ticket-4711/messages -X POST \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"text":"Mein Terminal ist offline.","language":"de"}'

{"conversation_id":"ticket-4711","reply":"…","ended":false,"escalate_to_human":false}

escalate_to_human ist das Feld, auf das es ankommt. Steht es auf true, hat der Agent erkannt, dass er den Fall nicht tragen soll. Behandeln Sie es als Übergabe an einen Menschen, nicht als Fehler. escalate_to_human is the field that matters. When it is true, the agent has recognised that it should not carry this case. Treat it as a handover to a person, not as an error.

Schreiben erfordert den Scope write. Ein Nur-Lese-Schlüssel erhält hier 403, nicht 401 — der Schlüssel ist gültig, die Befugnis fehlt. Writing needs the write scope. A read-only key gets 403 here, not 401 — the key is valid, the permission is not there.

05 · Benachrichtigt werdenGet told about things

Fragen Sie zuerst /v1/events ab, welche Ereignisse es gibt. Das Secret erscheint genau einmal — bei der Registrierung. Ask /v1/events first for the event types that exist. The secret appears exactly once — at registration.

curl -s $ACP/v1/webhooks -X POST \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"url":"https://erp.acme.de/hooks/acp","events":["conversation.closed"]}'

Prüfen Sie die Signatur, bevor Sie einer Zustellung glauben. Jede trägt X-ACP-Signature: t=<unix>,v1=<hmac> — ein HMAC-SHA256 über "{t}.{rohbody}" mit Ihrem Secret. Der Zeitstempel ist Teil der signierten Daten, damit eine abgefangene Zustellung nicht beliebig oft wiederholt werden kann; weisen Sie ein zu altes t ab. Verify the signature before believing a delivery. Each one carries X-ACP-Signature: t=<unix>,v1=<hmac> — an HMAC-SHA256 over "{t}.{raw body}" with your secret. The timestamp is part of the signed data so an intercepted delivery cannot be replayed indefinitely; reject a t that is too old.

import hmac, time
from hashlib import sha256

def verify(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    if abs(time.time() - int(parts["t"])) > tolerance:
        return False                     # too old to accept — a replay
    expected = hmac.new(secret.encode(),
                        f'{parts["t"]}.'.encode() + raw_body, sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])   # never ==

Signieren Sie über den rohen Body. Wer erst JSON parst und neu serialisiert, signiert etwas anderes als wir — und die Prüfung schlägt zu Recht fehl. Sign over the raw body. Parsing the JSON and re-serialising it signs something other than what we signed — and the check will rightly fail.

06 · Das Widget auf Ihre SeiteThe widget on your page

Ein Script-Tag. Es rendert in einem Shadow Root, Ihr CSS kann es nicht zerbrechen und sein CSS nicht in Ihre Seite auslaufen. One script tag. It renders in a shadow root, so your CSS cannot break it and its CSS cannot leak into your page.

<script src="$ACP/static/widget/acp-widget.js"
        data-key="acp_pk_…" data-lang="de" async></script>

Der öffentliche Schlüssel ist an eine Herkunfts-Liste gebunden. Der Browser setzt Origin, und eine Seite kann ihn nicht fälschen — ein von Ihrer Seite kopierter Schlüssel funktioniert auf einer fremden Domain nicht. Nennen Sie uns jede Domain, auch Staging; eine leere Liste erlaubt nichts. The public key is bound to an origin allow-list. The browser sets Origin and a page cannot forge it — a key lifted from your site does not work on anyone else's. Give us every domain, staging included; an empty list allows nothing.

Die KI-Offenlegung kommt vom Server und wird als erste Nachricht gezeigt, bevor der Besucher tippen kann (EU-KI-VO Art. 50). Sie ist nicht abschaltbar. The AI disclosure comes from the server and is shown as the opening message before the visitor can type (EU AI Act Art. 50). It cannot be switched off.

Was heute noch nicht gehtWhat does not work yet

Damit Sie es nicht durch Ausprobieren herausfinden. So you do not discover it by trying.

Keine Idempotenz-SchlüsselNo idempotency keys Ein wiederholtes POST wirkt zweimal. Wiederholen Sie Schreibzugriffe nicht blind.A retried POST acts twice. Do not blindly retry writes.
Keine Ratenbegrenzung pro SchlüsselNo per-key rate limit Begrenzen Sie auf Ihrer Seite. Wir verlassen uns derzeit auf Ihr Augenmaß.Throttle on your side. We currently rely on your restraint.
Keine Selbstverwaltung von SchlüsselnNo self-service keys Ausstellen und Sperren laufen über uns. Bewusst: so kann eine übernommene Konsolensitzung keinen Schlüssel erzeugen.Issuing and revoking go through us. Deliberate: a hijacked console session cannot mint a key.
Ausgehende Anrufe nur mit MenschOutbound calls need a person § 7 UWG: ein ausgehender Anruf braucht einen benannten menschlichen Auslöser. Chat und E-Mail dürfen autonom raus, bei vorhandener Rechtsgrundlage.§ 7 UWG: an outbound call needs a named human initiator. Chat and email may be dispatched autonomously given a lawful basis.