API - Telefonie / CTI Admin
📕 Für Administratoren und Entwickler.
Die CTI-Endpunkte (Computer-Telephony-Integration) ermöglichen die Anbindung einer externen CTI-Middleware an spiritflow. Typischer Anwendungsfall: Eine Middleware verbindet sich mit der Telefonanlage (z.B. FritzBox, Asterisk) und kommuniziert über diese API mit spiritflow.
Basis-Pfad: /api/v1/cti
DSGVO-Hinweis: Die CTI-Integration verarbeitet Telefonnummern anrufender Personen. Stellen Sie sicher, dass die Speicherung und Verarbeitung dieser Daten mit Ihrer Datenschutzerklaerung und den gesetzlichen Anforderungen vereinbar ist. Telefonnummern werden ausschließlich mandantenweit gespeichert und nicht an Dritte weitergegeben.
Ablauf einer CTI-Integration
Telefonanlage <-> CTI-Middleware <-> spiritflow Public API
- Eingehender Anruf: TK-Anlage meldet Anruf an die Middleware. Middleware ruft
POST /events/incoming-callauf. spiritflow zeigt dem zugeordneten Benutzer einen Screen-Pop mit Kundeninformationen. - Click-to-Dial: Benutzer klickt eine Telefonnummer in spiritflow an. spiritflow sendet den Webhook
cti.dial_requested. Die Middleware empfaengt den Webhook und initiiert den Anruf über die TK-Anlage. - Reverse Lookup: Middleware oder Frontend fragt
GET /lookupan. spiritflow ordnet die Nummer einem Kunden zu.
Rufnummernsuche (Reverse Lookup)
GET /api/v1/cti/lookup?phone={nummer}
Scope: cti:read
Sucht anhand einer Telefonnummer nach passenden Kunden und Kontaktpersonen. Die Nummer wird automatisch normalisiert (Sonderzeichen, Landesvorwahl). Die Suche erfolgt per Suffix-Matching über die letzten 7 Ziffern.
Query-Parameter:
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
phone | string | Ja | Telefonnummer (beliebiges Format) |
Antwort:
{
"data": [
{
"customerId": 42,
"customerName": "Muster GmbH",
"customerNumber": "K-2025-001",
"matchedField": "phone",
"matchedNumber": "+49 211 12345678",
"contactPerson": null
},
{
"customerId": 55,
"customerName": "Beispiel AG",
"customerNumber": "K-2025-015",
"matchedField": "mobile",
"matchedNumber": "+49 170 9876543",
"contactPerson": {
"id": 12,
"firstName": "Anna",
"lastName": "Müller",
"matchedField": "mobile",
"matchedNumber": "+49 170 9876543"
}
}
],
"meta": {
"requestId": "...",
"timestamp": "2025-03-01T10:30:00Z"
}
}
cURL-Beispiel:
curl -X GET "https://app.spiritflow.team/api/v1/cti/lookup?phone=+4921112345678" \
-H "X-API-Key: sf_live_xxxxx"
Hinweis: Die Suche durchsucht die Felder phone und mobile sowohl bei Kunden als auch bei aktiven Kontaktpersonen. Ergebnisse sind auf den eigenen Mandanten beschränkt. Archivierte Kunden werden nicht gefunden.
Nebenstellen-Zuordnung (Device Mappings)
GET /api/v1/cti/device-mappings
Scope: cti:read
Liefert eine Liste aller Benutzer, die eine CTI-Nebenstelle konfiguriert haben. Die Middleware nutzt diese Information, um eingehende Anrufe dem richtigen Benutzer zuzuordnen.
Antwort:
{
"data": [
{
"userId": 2,
"username": "florian.cremer",
"displayName": "Florian Cremer",
"device": "201"
},
{
"userId": 5,
"username": "anna.mueller",
"displayName": "Anna Müller",
"device": "**610"
}
],
"meta": {
"requestId": "...",
"timestamp": "2025-03-01T10:30:00Z"
}
}
cURL-Beispiel:
curl -X GET "https://app.spiritflow.team/api/v1/cti/device-mappings" \
-H "X-API-Key: sf_live_xxxxx"
Hinweis: Administratoren konfigurieren die Nebenstellen der einzelnen Benutzer in spiritflow unter Einstellungen > Benutzerverwaltung > Benutzer-Dialog > Tab Arbeitseinstellungen > Telefonie (CTI).
Eingehenden Anruf melden (Screen-Pop)
POST /api/v1/cti/events/incoming-call
Scope: cti:write
Meldet einen eingehenden Anruf. spiritflow fuehrt automatisch eine Rufnummernsuche durch und zeigt dem zugeordneten Benutzer eine Echtzeit-Benachrichtigung (Screen-Pop) mit Kundeninformationen an.
Request-Body:
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
callerNumber | string | Ja | Anrufende Telefonnummer |
calledDevice | string | Ja | Angerufene Nebenstelle (z.B. "201", "**610") |
callId | string | Nein | Eindeutige Call-ID der TK-Anlage |
timestamp | string | Nein | ISO 8601 Zeitstempel des Anrufs |
cURL-Beispiel:
curl -X POST "https://app.spiritflow.team/api/v1/cti/events/incoming-call" \
-H "X-API-Key: sf_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"callerNumber": "+49 211 12345678",
"calledDevice": "201",
"callId": "call-2025-03-01-001"
}'
Antwort: HTTP 202 Accepted
{
"data": {
"processed": true,
"targetUserId": 2,
"customerFound": true,
"customerId": 42
},
"meta": {
"requestId": "...",
"timestamp": "2025-03-01T10:30:00Z"
}
}
Verhalten:
| Situation | Ergebnis |
|---|---|
| Nebenstelle zugeordnet + Kunde gefunden | Screen-Pop mit Kundenname, Klick navigiert zum Kunden |
| Nebenstelle zugeordnet + Kunde unbekannt | Screen-Pop mit Telefonnummer |
| Nebenstelle nicht zugeordnet | processed: false, keine Benachrichtigung |
Anruf angenommen melden (Call Connected)
POST /api/v1/cti/events/call-connected
Scope: cti:write
Meldet an spiritflow, dass ein Anruf auf einer bestimmten Nebenstelle angenommen wurde. Die Anruf-Benachrichtigungen werden bei allen anderen Benutzern entfernt.
Request-Body:
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
callId | string | Ja | Eindeutige Call-ID der TK-Anlage |
device | string | Ja | Nebenstelle, die den Anruf angenommen hat |
callerNumber | string | Nein | Anrufende Telefonnummer |
cURL-Beispiel:
curl -X POST "https://app.spiritflow.team/api/v1/cti/events/call-connected" \
-H "X-API-Key: sf_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"callId": "call-2025-03-01-001",
"device": "201"
}'
Antwort: HTTP 202 Accepted
{
"data": {
"processed": true,
"answeredByUserId": 2,
"notificationsDismissed": 3
},
"meta": {
"requestId": "...",
"timestamp": "2025-03-01T10:30:00Z"
}
}
Anruf-Ende melden (Call Ended)
POST /api/v1/cti/events/call-ended
Scope: cti:write
Meldet das Ende eines Anrufs an spiritflow. Bei nicht angenommenen Anrufen (answered: false) werden die zugehoerigen Ring-Benachrichtigungen entfernt. Bei angenommenen Anrufen wird ein Aktivitaets-Eintrag im Rueckblick angelegt.
Request-Body:
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
callId | string | Ja | Eindeutige Call-ID der TK-Anlage |
duration | number | Nein | Dauer des Anrufs in Sekunden (null wenn nicht angenommen) |
answered | boolean | Nein | Ob der Anruf angenommen wurde (Standard: false) |
answeredByDevice | string | Nein | Nebenstelle, die den Anruf angenommen hat |
callerNumber | string | Nein | Anrufende Telefonnummer |
cURL-Beispiel:
curl -X POST "https://app.spiritflow.team/api/v1/cti/events/call-ended" \
-H "X-API-Key: sf_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"callId": "call-2025-03-01-001",
"duration": 120,
"answered": true,
"answeredByDevice": "201",
"callerNumber": "+49 211 12345678"
}'
Antwort: HTTP 202 Accepted
{
"data": {
"processed": true,
"notificationsRemoved": 1,
"activityCreated": true
},
"meta": {
"requestId": "...",
"timestamp": "2025-03-01T10:30:00Z"
}
}
Click-to-Dial (Webhook)
Click-to-Dial wird nicht über die Public API aufgerufen, sondern über einen Webhook-Event. Wenn ein Benutzer in spiritflow auf eine Telefonnummer klickt, wird der Webhook cti.dial_requested an alle konfigurierten Webhook-Endpunkte gesendet.
Webhook-Payload:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"event": "cti.dial_requested",
"created_at": "2025-03-01T10:30:00Z",
"source": "ui",
"actor": {
"id": 2,
"type": "user",
"name": "Florian Cremer"
},
"data": {
"targetNumber": "+49 211 12345678",
"sourceDevice": "201",
"userId": 2,
"username": "florian.cremer",
"customerId": 42,
"contactPersonId": null
},
"changes": {}
}
Die CTI-Middleware empfaengt diesen Webhook und initiiert den Anruf von der Nebenstelle (sourceDevice) zur Zielnummer (targetNumber) über die Telefonanlage.
Voraussetzungen für Click-to-Dial:
- Webhook mit Event
cti.dial_requestedmuss eingerichtet sein - Der Benutzer muss eine Nebenstelle konfiguriert haben
- Die CTI-Middleware muss den Webhook empfangen und verarbeiten