Talkward API
v1The API connects Talkward to your own systems: read conversations and contacts, send messages, set status, tags and fields, get notified of new events by webhook and post updates to team channels. Make, Zapier and n8n have ready-made building blocks as separate add-ons; they use the same API.
https://chat.talkward.app/api/v1You create the key in Talkward under Settings › Add-ons › API. The API is included from Professional at no extra cost.
Authentication
Create a key under Settings › Add-ons › API and send it with every request in the Authorization header:
Authorization: Bearer tw_…
Instead of Authorization you can use the header X-API-Key: tw_…. A key belongs to exactly one workspace and only sees its data. Once you revoke it, every connection using it stops immediately. Keep the key like a password and only use it on your server, never in the browser.
When creating the key you choose its permissions: Read and write or Read only. A read-only key may make every GET call; any other call ends with 403 integration.nur_lesen. That suits reporting, dashboards and service providers who should not change anything.
Responses and errors
All responses are JSON. Successful responses carry "ok": true. Errors come with a matching HTTP status and a code, for example {"ok": false, "fehler": "konversation.nicht_gefunden"}.
| Status | Meaning |
|---|---|
| 400 | Invalid input (the code names the field, e.g. verfassen.adresse) |
| 401 | Key missing, wrong or revoked (integration.token_ungueltig) |
| 403 | Feature not enabled (berechtigung.fehlt with funktion) or read-only key (integration.nur_lesen) |
| 404 | Conversation, contact, brand, attachment or webhook does not exist |
| 409 | Conversation is archived, or the same Idempotency-Key is still running (api.idempotenz_laeuft) |
| 422 | Same Idempotency-Key with different content (api.idempotenz_anders) |
| 429 | Too many requests; Retry-After gives the seconds until the next attempt |
Limits
Each key may make 300 requests per minute. Every response reports the state in three headers:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests per minute (300) |
X-RateLimit-Remaining | Still available this minute |
X-RateLimit-Reset | Seconds until the minute starts over |
Once the quota is used up you get 429 with Retry-After (seconds). Timestamps are ISO 8601 with time zone, for example 2026-09-25T09:14:00+00:00.
Pagination and sync
Lists return at most limit entries. If there are more, the response contains weiter (next): pass this value as nach (after) on the next call until weiter is empty (null). For a regular sync with your system use geaendert_seit (changed since, the time of your last sync): you then only get conversations or contacts that changed since then.
GET /gespraeche?geaendert_seit=2026-09-29T06:00:00Z&limit=100
GET /gespraeche?geaendert_seit=2026-09-29T06:00:00Z&limit=100&nach=MjAyNi0wOS0yOVQwNzoxMjo…
Retrying without duplicates
If a connection drops, your system does not know whether a message already went out. So send the header Idempotency-Key with write calls, a unique value of your own per operation (for example your order number or a UUID, at most 200 characters):
Idempotency-Key: shipping-10234
Talkward remembers the response for 24 hours. If the same call arrives again with the same key, Talkward returns the remembered response with the header Idempotent-Replayed: true instead of sending the message a second time. Errors are not remembered; after an error you may retry with the same key. Make, Zapier and n8n retry failed steps automatically, so the key is especially worthwhile there.
Objects
Field names are German, as in the product. A conversation (gespraech) looks like this:
{
"id": 101,
"marke": "bertrand",
"marke_name": "BERTRAND",
"kanal": "whatsapp",
"status": "mensch",
"spam": false,
"ungelesen": true,
"zugewiesen": "anna@shop.de",
"abteilung": {
"id": 3,
"name": "Shipping"
},
"kunde": {
"name": "Nina Neu",
"mail": "nina@example.com",
"telefon": "+4915112345678"
},
"betreff": null,
"sprache": "de",
"auftrag": "10234",
"tags": [
"VIP"
],
"felder": {
"Kundennummer": "4711"
},
"erstellt": "2026-09-25T09:12:00+00:00",
"aktualisiert": "2026-09-25T09:14:00+00:00",
"link": "https://chat.talkward.app/#/posteingang/haupt/101"
}
marke is the brand, kanal the channel, kunde the customer, zugewiesen the assignee, abteilung the department, felder custom fields, auftrag the order number. status is ki (the AI is answering), mensch (with the team) or erledigt (done). A message (nachricht):
{
"id": 5012,
"von": "kunde",
"text": "Where is my order?",
"mitarbeiter": null,
"anhaenge": [
{
"id": "Xy3kQ9bT2mLp",
"name": "invoice.pdf",
"mime": "application/pdf",
"groesse": 48211,
"url": "https://chat.talkward.app/api/v1/gespraeche/101/anhaenge/Xy3kQ9bT2mLp"
}
],
"erstellt": "2026-09-25T09:14:00+00:00"
}
von (sender) is kunde (customer), mitarbeiter (team member), ki (AI) or notiz (internal note). Download an attachment's url with the same key (see Download an attachment).
Workspace
Check the connection
/api/v1/ichShows which workspace the key belongs to. A good first call to test the key.
curl "https://chat.talkward.app/api/v1/ich" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/ich', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/ich",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/ich', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"mandant": {
"id": "6f1c…",
"name": "Haferhain Ltd"
},
"schluessel": {
"name": "ERP",
"art": "allgemein",
"rechte": "alles"
}
}
List brands
/api/v1/markenAll active brands of the workspace. You need the key for marke in other calls.
curl "https://chat.talkward.app/api/v1/marken" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/marken', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/marken",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/marken', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"marken": [
{
"key": "haferhain",
"name": "Haferhain"
}
]
}
List team members
/api/v1/teamAll active team members with their availability. anwesenheit is da (available), pause (break) or abwesend (away); each member sets it themselves. An expired "away until" counts as da again. abwesend_bis is only set for abwesend with a date.
curl "https://chat.talkward.app/api/v1/team" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/team', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/team",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/team', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"team": [
{
"login": "anna@shop.de",
"name": "Anna",
"anwesenheit": "da",
"abwesend_bis": null
}
]
}
List departments
/api/v1/abteilungenDepartments with routing rule and members. regel is alle (all members) or belastung (least busy). Without the abteilungen feature (from Professional) the list is empty.
curl "https://chat.talkward.app/api/v1/abteilungen" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/abteilungen', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/abteilungen",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/abteilungen', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"abteilungen": [
{
"id": 3,
"name": "Shipping",
"regel": "belastung",
"mitglieder": [
"anna@shop.de"
]
}
]
}
List tags
/api/v1/tagsAll tags used on conversations and segments used on contacts, with counts, most frequent first. Handy for dropdowns in Make, Zapier or n8n.
curl "https://chat.talkward.app/api/v1/tags" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/tags', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/tags",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/tags', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"gespraeche": [
{
"name": "VIP",
"anzahl": 42
}
],
"kontakte": [
{
"name": "Newsletter",
"anzahl": 310
}
]
}
curl "https://chat.talkward.app/api/v1/felder" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/felder', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/felder",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/felder', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"gespraeche": [
"Customer number"
],
"kontakte": [
"Customer number",
"Loyalty tier"
]
}
List WhatsApp templates
/api/v1/marken/{marke}/whatsapp-vorlagenThe templates approved by Meta for this brand's WhatsApp number. parameter is the number of placeholders {{1}}, {{2}}, … in the text. Without a WhatsApp number set up you get 400 whatsapp.nicht_eingerichtet.
curl "https://chat.talkward.app/api/v1/marken/haferhain/whatsapp-vorlagen" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/marken/haferhain/whatsapp-vorlagen', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/marken/haferhain/whatsapp-vorlagen",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/marken/haferhain/whatsapp-vorlagen', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"vorlagen": [
{
"name": "shipping_info",
"sprache": "en",
"text": "Hi {{1}}, your parcel {{2}} is on its way.",
"parameter": 2,
"kategorie": "UTILITY"
}
]
}
Conversations
Every change to a conversation appears as a line in its history.
List conversations
/api/v1/gespraecheConversations of the workspace, most recently updated first.
Query parameters
kontaktstringCustomer email address or phone number
statusstringoffen(open),ki,menschorerledigtmarkestringOnly conversations of this brand (
key)geaendert_seitstringOnly conversations changed since this time (ISO 8601 with time zone)
limitinteger1 to 100, default 20
nachstringValue of
weiterfrom the previous response, for the next page
curl "https://chat.talkward.app/api/v1/gespraeche?status=mensch&limit=20" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche?status=mensch&limit=20', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/gespraeche",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
params={
"status": "mensch",
"limit": 20,
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/gespraeche', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'query' => [
'status' => 'mensch',
'limit' => 20,
],
]);
echo $res->getBody();
{
"ok": true,
"gespraeche": [
{
"id": 101,
"marke": "haferhain",
"kanal": "whatsapp",
"status": "mensch",
"…": "…"
}
],
"weiter": "MjAyNi0wOS0yNVQwOToxNDowMCswMDowMHwxMDE"
}
curl "https://chat.talkward.app/api/v1/gespraeche/101" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche/101', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/gespraeche/101",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/gespraeche/101', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"gespraech": {
"id": 101,
"marke": "haferhain",
"kanal": "whatsapp",
"status": "mensch",
"…": "…"
}
}
List messages
/api/v1/gespraeche/{id}/nachrichtenThe history of a conversation, oldest first. Internal notes only on request. Without vor and nach you get the latest limit messages. mehr (more) tells whether there are further ones in that direction.
Query parameters
notizenboolean1includes internal noteslimitinteger1 to 500, default 50
vorintegerMessage ID: the messages before it (load older ones)
nachintegerMessage ID: the messages after it (fetch new ones)
curl "https://chat.talkward.app/api/v1/gespraeche/101/nachrichten?notizen=1&limit=50" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche/101/nachrichten?notizen=1&limit=50', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/gespraeche/101/nachrichten",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
params={
"notizen": 1,
"limit": 50,
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/gespraeche/101/nachrichten', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'query' => [
'notizen' => 1,
'limit' => 50,
],
]);
echo $res->getBody();
{
"ok": true,
"nachrichten": [
{
"id": 5012,
"von": "kunde",
"text": "Where is my order?",
"mitarbeiter": null,
"anhaenge": [],
"erstellt": "2026-09-25T09:14:00+00:00"
}
],
"mehr": false
}
Download an attachment
/api/v1/gespraeche/{id}/anhaenge/{anhang}The file of an attachment, always as a download. You find the link as url in anhaenge of each message.
curl "https://chat.talkward.app/api/v1/gespraeche/101/anhaenge/Xy3kQ9bT2mLp" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche/101/anhaenge/Xy3kQ9bT2mLp', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/gespraeche/101/anhaenge/Xy3kQ9bT2mLp",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/gespraeche/101/anhaenge/Xy3kQ9bT2mLp', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
Send a reply
/api/v1/gespraeche/{id}/nachrichtenThe message goes to the customer immediately through the conversation's channel. The inbox shows the name of your key as the sender. WhatsApp's 24-hour window applies: if the customer has not written for longer, WhatsApp requires a template (see Send a WhatsApp template) and the response reports zugestellt: false (not delivered).
Body
textstringRequired (one of both)Text to the customer (an attachment alone is enough)
anhaengeobject[]Up to 5 files:
dateiname(file name),inhalt(Base64 content),mime(optional); at most 15 MB each; images, PDF, Office files
curl -X POST "https://chat.talkward.app/api/v1/gespraeche/101/nachrichten" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Please find your invoice attached.",
"anhaenge": [
{
"dateiname": "invoice-10234.pdf",
"inhalt": "JVBERi0xLjQK…"
}
]
}'
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche/101/nachrichten', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"text": "Please find your invoice attached.",
"anhaenge": [
{
"dateiname": "invoice-10234.pdf",
"inhalt": "JVBERi0xLjQK…"
}
]
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/gespraeche/101/nachrichten",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"text": "Please find your invoice attached.",
"anhaenge": [
{
"dateiname": "invoice-10234.pdf",
"inhalt": "JVBERi0xLjQK…",
},
],
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/gespraeche/101/nachrichten', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'text' => 'Please find your invoice attached.',
'anhaenge' => [
[
'dateiname' => 'invoice-10234.pdf',
'inhalt' => 'JVBERi0xLjQK…',
],
],
],
]);
echo $res->getBody();
{
"ok": true,
"nachricht": {
"id": 5013,
"von": "mitarbeiter",
"…": "…"
},
"zugestellt": true,
"gespraech": {
"id": 101,
"…": "…"
}
}
Send a WhatsApp template
/api/v1/gespraeche/{id}/vorlageSends a template approved by Meta into a WhatsApp conversation, also after the 24-hour window. Typical for shipping updates, appointment reminders or getting back to someone after days. The history shows the text as the customer receives it.
Body
namestringRequiredTemplate name (see List WhatsApp templates)
sprachestringTemplate language, default
deparameterstring[]Values for
{{1}},{{2}}, …; exactly as many as the template has
curl -X POST "https://chat.talkward.app/api/v1/gespraeche/101/vorlage" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "shipping_info",
"sprache": "en",
"parameter": [
"Nina",
"10234"
]
}'
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche/101/vorlage', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "shipping_info",
"sprache": "en",
"parameter": [
"Nina",
"10234"
]
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/gespraeche/101/vorlage",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"name": "shipping_info",
"sprache": "en",
"parameter": ["Nina", "10234"],
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/gespraeche/101/vorlage', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'name' => 'shipping_info',
'sprache' => 'en',
'parameter' => ['Nina', '10234'],
],
]);
echo $res->getBody();
{
"ok": true,
"nachricht": {
"id": 5030,
"text": "Hi Nina, your parcel 10234 is on its way.",
"…": "…"
},
"zugestellt": true,
"gespraech": {
"id": 101,
"…": "…"
}
}
Write a new message
/api/v1/nachrichtenWrites to an email address or WhatsApp number. If there is an open conversation for brand and address, the message goes there; otherwise a new one is created (neu: true).
Body
markestringRequiredBrand (
key) to send fromkanalstringRequiredmailorwhatsappanstringRequiredEmail address or phone number with country code
textstringRequired (one of both)Message text (not needed with
vorlageor when an attachment is included)anhaengeobject[]Files as for Send a reply
vorlageobjectWhatsApp only:
{name, sprache, parameter}instead of text; needed if the customer has not written in the last 24 hoursnamestringCustomer name
betreffstringSubject (email only)
statusstringSet afterwards:
erledigt,an_kioran_mensch
curl -X POST "https://chat.talkward.app/api/v1/nachrichten" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"marke": "haferhain",
"kanal": "mail",
"an": "nina@example.com",
"name": "Nina Neu",
"betreff": "Your order 10234",
"text": "Hello, your order is on its way."
}'
const res = await fetch('https://chat.talkward.app/api/v1/nachrichten', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"marke": "haferhain",
"kanal": "mail",
"an": "nina@example.com",
"name": "Nina Neu",
"betreff": "Your order 10234",
"text": "Hello, your order is on its way."
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/nachrichten",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"marke": "haferhain",
"kanal": "mail",
"an": "nina@example.com",
"name": "Nina Neu",
"betreff": "Your order 10234",
"text": "Hello, your order is on its way.",
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/nachrichten', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'marke' => 'haferhain',
'kanal' => 'mail',
'an' => 'nina@example.com',
'name' => 'Nina Neu',
'betreff' => 'Your order 10234',
'text' => 'Hello, your order is on its way.',
],
]);
echo $res->getBody();
{
"ok": true,
"nachricht": {
"id": 5020,
"…": "…"
},
"zugestellt": true,
"neu": true,
"gespraech": {
"id": 102,
"…": "…"
}
}
Add a note
/api/v1/gespraeche/{id}/notizenAn internal note. The customer does not see it.
Body
textstringRequiredNote text
curl -X POST "https://chat.talkward.app/api/v1/gespraeche/101/notizen" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Customer called about this."
}'
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche/101/notizen', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"text": "Customer called about this."
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/gespraeche/101/notizen",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"text": "Customer called about this.",
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/gespraeche/101/notizen', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'text' => 'Customer called about this.',
],
]);
echo $res->getBody();
{
"ok": true,
"nachricht": {
"id": 5014,
"von": "notiz",
"text": "Customer called about this.",
"…": "…"
}
}
Set status
/api/v1/gespraeche/{id}/statusBody
statusstringRequirederledigt(done),offen(open),an_ki(to AI),an_mensch(to team) orspam
curl -X POST "https://chat.talkward.app/api/v1/gespraeche/101/status" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "erledigt"
}'
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche/101/status', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"status": "erledigt"
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/gespraeche/101/status",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"status": "erledigt",
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/gespraeche/101/status', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'status' => 'erledigt',
],
]);
echo $res->getBody();
{
"ok": true,
"gespraech": {
"id": 101,
"status": "erledigt",
"…": "…"
}
}
Assign a conversation
/api/v1/gespraeche/{id}/zuweisenBody
loginstringRequiredTeam member login; empty removes the assignment
curl -X POST "https://chat.talkward.app/api/v1/gespraeche/101/zuweisen" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"login": "anna@shop.de"
}'
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche/101/zuweisen', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"login": "anna@shop.de"
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/gespraeche/101/zuweisen",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"login": "anna@shop.de",
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/gespraeche/101/zuweisen', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'login' => 'anna@shop.de',
],
]);
echo $res->getBody();
{
"ok": true,
"gespraech": {
"id": 101,
"zugewiesen": "anna@shop.de",
"…": "…"
}
}
Set department
/api/v1/gespraeche/{id}/abteilungHands the conversation to the department according to its routing rule: with alle it stays with the department, with belastung it goes to the available member with the fewest open conversations and then shows under zugewiesen. 403 without the abteilungen feature, 404 for an unknown department.
Body
abteilungintegerRequiredDepartment ID;
nullremoves it
curl -X POST "https://chat.talkward.app/api/v1/gespraeche/101/abteilung" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"abteilung": 3
}'
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche/101/abteilung', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"abteilung": 3
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/gespraeche/101/abteilung",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"abteilung": 3,
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/gespraeche/101/abteilung', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'abteilung' => 3,
],
]);
echo $res->getBody();
{
"ok": true,
"gespraech": {
"id": 101,
"abteilung": {
"id": 3,
"name": "Shipping"
},
"…": "…"
}
}
curl -X POST "https://chat.talkward.app/api/v1/gespraeche/101/tags" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"hinzu": [
"VIP"
],
"weg": [
"Return"
]
}'
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche/101/tags', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"hinzu": [
"VIP"
],
"weg": [
"Return"
]
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/gespraeche/101/tags",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"hinzu": ["VIP"],
"weg": ["Return"],
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/gespraeche/101/tags', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'hinzu' => ['VIP'],
'weg' => ['Return'],
],
]);
echo $res->getBody();
{
"ok": true,
"gespraech": {
"id": 101,
"tags": [
"VIP"
],
"…": "…"
}
}
Set fields
/api/v1/gespraeche/{id}/felderBody
felderobjectRequiredName and value per field; an empty value removes the field
curl -X POST "https://chat.talkward.app/api/v1/gespraeche/101/felder" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"felder": {
"Customer number": "4711"
}
}'
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche/101/felder', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"felder": {
"Customer number": "4711"
}
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/gespraeche/101/felder",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"felder": {
"Customer number": "4711",
},
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/gespraeche/101/felder', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'felder' => [
'Customer number' => '4711',
],
],
]);
echo $res->getBody();
{
"ok": true,
"gespraech": {
"id": 101,
"felder": {
"Customer number": "4711"
},
"…": "…"
}
}
Update customer details
/api/v1/gespraeche/{id}/kontaktName, email address or phone number of the customer in this conversation.
Body
namestringCustomer name
mailstringEmail address
telefonstringPhone number with country code
curl -X POST "https://chat.talkward.app/api/v1/gespraeche/101/kontakt" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Nina Neu",
"telefon": "+4915112345678"
}'
const res = await fetch('https://chat.talkward.app/api/v1/gespraeche/101/kontakt', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Nina Neu",
"telefon": "+4915112345678"
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/gespraeche/101/kontakt",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"name": "Nina Neu",
"telefon": "+4915112345678",
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/gespraeche/101/kontakt', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'name' => 'Nina Neu',
'telefon' => '+4915112345678',
],
]);
echo $res->getBody();
{
"ok": true,
"gespraech": {
"id": 101,
"kunde": {
"name": "Nina Neu",
"…": "…"
},
"…": "…"
}
}
Contacts
Fetch all contacts
/api/v1/kontakte/profileAll contact profiles from the Contacts area, by ascending ID. To page, pass weiter as nach; for syncing use geaendert_seit.
Query parameters
suchestringName, email or phone
segmentstringOnly contacts with this segment
geaendert_seitstringOnly contacts changed since then (ISO 8601 with time zone)
limitinteger1 to 200, default 50
nachintegerValue of
weiterfrom the previous response
curl "https://chat.talkward.app/api/v1/kontakte/profile?segment=Newsletter&limit=50" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/kontakte/profile?segment=Newsletter&limit=50', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/kontakte/profile",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
params={
"segment": "Newsletter",
"limit": 50,
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/kontakte/profile', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'query' => [
'segment' => 'Newsletter',
'limit' => 50,
],
]);
echo $res->getBody();
{
"ok": true,
"kontakte": [
{
"id": 42,
"name": "Nina Neu",
"mail": "nina@example.com",
"tags": [
"Newsletter"
],
"…": "…"
}
],
"weiter": 42
}
curl "https://chat.talkward.app/api/v1/kontakte?suche=nina%40example.com" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/kontakte?suche=nina%40example.com', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/kontakte",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
params={
"suche": "nina@example.com",
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/kontakte', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'query' => [
'suche' => 'nina@example.com',
],
]);
echo $res->getBody();
{
"ok": true,
"kontakte": [
{
"schluessel": "nina@example.com",
"name": "Nina Neu",
"mails": [
"nina@example.com"
],
"telefone": [],
"marken": [
"haferhain"
],
"letztes_gespraech": 101,
"offen": 1
}
]
}
Retrieve a contact
/api/v1/kontakte/{id}The contact profile from the Contacts area with segments, fields, company, key figures and the events of the timeline.
curl "https://chat.talkward.app/api/v1/kontakte/42" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/kontakte/42', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/kontakte/42",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/kontakte/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"kontakt": {
"id": 42,
"name": "Nina Neu",
"mail": "nina@example.com",
"…": "…"
},
"ereignisse": [],
"link": "https://chat.talkward.app/#/kontakte/42"
}
Create or update a contact
/api/v1/kontakteIf the person already exists (same email or phone number), empty fields are filled in; segments and fields are added. One of mail and telefon is required.
Body
mailstringRequired (one of both)Email address
telefonstringRequired (one of both)Phone number with country code
namestringName
sprachestringLanguage, e.g.
enlandstringCountry as ISO code, e.g.
GBstadtstringCity
firmastringCompany
positionstringPosition in the company
websitestringWebsite
tagsstring[]Segments
felderobjectCustom fields, name and value
curl -X POST "https://chat.talkward.app/api/v1/kontakte" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mail": "nina@example.com",
"name": "Nina Neu",
"land": "GB",
"tags": [
"Newsletter"
],
"felder": {
"Customer number": "4711"
}
}'
const res = await fetch('https://chat.talkward.app/api/v1/kontakte', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"mail": "nina@example.com",
"name": "Nina Neu",
"land": "GB",
"tags": [
"Newsletter"
],
"felder": {
"Customer number": "4711"
}
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/kontakte",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"mail": "nina@example.com",
"name": "Nina Neu",
"land": "GB",
"tags": ["Newsletter"],
"felder": {
"Customer number": "4711",
},
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/kontakte', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'mail' => 'nina@example.com',
'name' => 'Nina Neu',
'land' => 'GB',
'tags' => ['Newsletter'],
'felder' => [
'Customer number' => '4711',
],
],
]);
echo $res->getBody();
{
"ok": true,
"kontakt": {
"id": 42,
"…": "…"
},
"neu": true,
"link": "https://chat.talkward.app/#/kontakte/42"
}
Update a contact
/api/v1/kontakte/{id}Only the fields you send change; an empty value ("") clears the field. tags and felder replace the existing ones. Name and language also flow into the person's conversations. If the new email or phone number already belongs to another contact you get 409 kontakt.vorhanden with its id.
Body
namestringName
mailstringEmail address
telefonstringPhone number with country code
sprache,land,stadt,firma,position,websitestringas when creating
tagsstring[]Segments (replace the existing ones)
felderobjectCustom fields (replace the existing ones)
curl -X PATCH "https://chat.talkward.app/api/v1/kontakte/42" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Nina Newman",
"stadt": "London",
"tags": [
"VIP",
"Newsletter"
]
}'
const res = await fetch('https://chat.talkward.app/api/v1/kontakte/42', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Nina Newman",
"stadt": "London",
"tags": [
"VIP",
"Newsletter"
]
}),
});
const daten = await res.json();
import os, requests
res = requests.patch(
"https://chat.talkward.app/api/v1/kontakte/42",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"name": "Nina Newman",
"stadt": "London",
"tags": ["VIP", "Newsletter"],
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('PATCH', 'https://chat.talkward.app/api/v1/kontakte/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'name' => 'Nina Newman',
'stadt' => 'London',
'tags' => ['VIP', 'Newsletter'],
],
]);
echo $res->getBody();
{
"ok": true,
"kontakt": {
"id": 42,
"name": "Nina Newman",
"…": "…"
},
"link": "https://chat.talkward.app/#/kontakte/42"
}
Delete a contact
/api/v1/kontakte/{id}Deletes the contact profile, for example at the person's request (GDPR Art. 17). With gespraeche=1 Talkward also deletes all of the person's conversations including messages and attachments, permanently and without a recycle bin.
Query parameters
gespraecheboolean1also deletes all conversations with the email address or phone number
curl -X DELETE "https://chat.talkward.app/api/v1/kontakte/42?gespraeche=1" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/kontakte/42?gespraeche=1', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.delete(
"https://chat.talkward.app/api/v1/kontakte/42",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
params={
"gespraeche": 1,
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('DELETE', 'https://chat.talkward.app/api/v1/kontakte/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'query' => [
'gespraeche' => 1,
],
]);
echo $res->getBody();
{
"ok": true,
"geloescht": {
"kontakt": 42,
"gespraeche": 3,
"dateien": 1
}
}
Export a data subject request
/api/v1/kontakte/{id}/exportEverything Talkward stores about a person (GDPR Art. 15): profile, events and all conversations with messages and internal notes, as one JSON file.
curl "https://chat.talkward.app/api/v1/kontakte/42/export" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/kontakte/42/export', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/kontakte/42/export",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/kontakte/42/export', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"erstellt": "2026-09-29T10:00:00+02:00",
"kontakt": {
"id": 42,
"…": "…"
},
"ereignisse": [],
"gespraeche": [
{
"gespraech": {
"id": 101,
"…": "…"
},
"nachrichten": [
{
"id": 5012,
"…": "…"
}
]
}
]
}
Track an event
/api/v1/kontakte/ereignisWrites an event to the timeline of the contact page. If the contact does not exist yet, it is created. The last 100 events per contact are kept.
Body
mailstringRequired (one of both)Email address (or
telefon)telefonstringRequired (one of both)Phone number (or
mail)namestringRequiredEvent name, e.g.
Order:CompleteddatenobjectAny values for the event
farbestringColour:
rot,orange,gelb,gruen,blau,lila,rosa,braun,grauorschwarz
curl -X POST "https://chat.talkward.app/api/v1/kontakte/ereignis" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mail": "nina@example.com",
"name": "Order:Completed",
"daten": {
"number": "10234",
"total": 49.9
},
"farbe": "gruen"
}'
const res = await fetch('https://chat.talkward.app/api/v1/kontakte/ereignis', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"mail": "nina@example.com",
"name": "Order:Completed",
"daten": {
"number": "10234",
"total": 49.9
},
"farbe": "gruen"
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/kontakte/ereignis",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"mail": "nina@example.com",
"name": "Order:Completed",
"daten": {
"number": "10234",
"total": 49.9,
},
"farbe": "gruen",
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/kontakte/ereignis', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'mail' => 'nina@example.com',
'name' => 'Order:Completed',
'daten' => [
'number' => '10234',
'total' => 49.9,
],
'farbe' => 'gruen',
],
]);
echo $res->getBody();
{
"ok": true,
"kontakt_id": 42,
"ereignis": {
"name": "Order:Completed",
"farbe": "gruen",
"…": "…"
}
}
Webhooks
With a webhook, Talkward reports events to your address immediately. The address must start with https:// and be publicly reachable.
| Event | When |
|---|---|
nachricht_neu | A customer writes |
nachricht_gesendet | A reply from the team, AI or an automation reached the customer |
gespraech_neu | A new conversation starts |
uebergabe | The conversation is handed to the team |
erledigt | The conversation is done |
wieder_offen | A finished conversation is open again |
zuweisung | The conversation is assigned to someone |
abteilung_zugewiesen | The conversation goes to a department |
tag | A tag is added |
notiz_neu | An internal note is added |
spam | The conversation is marked as spam |
meldung_neu | An alert via POST /meldungen came in |
kontakt_neu | A contact is created (from a conversation, by hand, by import or via API) |
kontakt_geaendert | A contact is changed |
kontakt_geloescht | A contact is deleted |
Create a webhook
/api/v1/webhooksThe response contains the geheimnis (secret) you use to verify the signature of each delivery. It is only shown this once.
Body
ereignisstringRequiredOne of the events above
urlstringRequiredYour address, starts with
https://markestringOnly events of this brand
curl -X POST "https://chat.talkward.app/api/v1/webhooks" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ereignis": "nachricht_neu",
"url": "https://example.com/talkward"
}'
const res = await fetch('https://chat.talkward.app/api/v1/webhooks', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"ereignis": "nachricht_neu",
"url": "https://example.com/talkward"
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/webhooks",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"ereignis": "nachricht_neu",
"url": "https://example.com/talkward",
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/webhooks', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'ereignis' => 'nachricht_neu',
'url' => 'https://example.com/talkward',
],
]);
echo $res->getBody();
{
"ok": true,
"id": "3f2a9c1e-…",
"ereignis": "nachricht_neu",
"url": "https://example.com/talkward",
"marke": null,
"aktiv": true,
"erstellt": "2026-09-25T09:00:00+00:00",
"geheimnis": "Jx8q…"
}
Test a webhook
/api/v1/webhooks/{id}/testImmediately sends a signed test event to the address and reports what came back. No retries, handy while setting up.
curl -X POST "https://chat.talkward.app/api/v1/webhooks/3f2a9c1e-7b4d-4e8a-9c2f-5d6e7f8a9b0c/test" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/webhooks/3f2a9c1e-7b4d-4e8a-9c2f-5d6e7f8a9b0c/test', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/webhooks/3f2a9c1e-7b4d-4e8a-9c2f-5d6e7f8a9b0c/test",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/webhooks/3f2a9c1e-7b4d-4e8a-9c2f-5d6e7f8a9b0c/test', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"ergebnis": {
"ok": true,
"status": 200,
"dauer_ms": 183
}
}
View deliveries
/api/v1/webhooks/{id}/zustellungenThe latest delivery attempts (newest first, at most 50 are kept) with status, duration and error, plus what is still waiting for a retry. This is how you find out why your system receives nothing.
Query parameters
limitinteger1 to 50, default 20
curl "https://chat.talkward.app/api/v1/webhooks/3f2a9c1e-7b4d-4e8a-9c2f-5d6e7f8a9b0c/zustellungen" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/webhooks/3f2a9c1e-7b4d-4e8a-9c2f-5d6e7f8a9b0c/zustellungen', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/webhooks/3f2a9c1e-7b4d-4e8a-9c2f-5d6e7f8a9b0c/zustellungen",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/webhooks/3f2a9c1e-7b4d-4e8a-9c2f-5d6e7f8a9b0c/zustellungen', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"webhook": {
"id": "3f2a9c1e-…",
"letzter_status": 500,
"fehler_folge": 2,
"…": "…"
},
"zustellungen": [
{
"zustellung": 88,
"ereignis": "nachricht_neu",
"versuch": 2,
"status": 500,
"dauer_ms": 312,
"fehler": null,
"erstellt": "2026-09-29T09:15:00+00:00"
}
],
"wartend": [
{
"zustellung": 88,
"ereignis": "nachricht_neu",
"versuche": 2,
"naechster_versuch": "2026-09-29T09:45:00+00:00"
}
]
}
curl "https://chat.talkward.app/api/v1/webhooks" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/webhooks', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/webhooks",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/webhooks', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true,
"webhooks": [
{
"id": "3f2a9c1e-…",
"ereignis": "nachricht_neu",
"url": "https://example.com/talkward",
"marke": null,
"aktiv": true
}
]
}
curl -X DELETE "https://chat.talkward.app/api/v1/webhooks/3f2a9c1e-7b4d-4e8a-9c2f-5d6e7f8a9b0c" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/webhooks/3f2a9c1e-7b4d-4e8a-9c2f-5d6e7f8a9b0c', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.delete(
"https://chat.talkward.app/api/v1/webhooks/3f2a9c1e-7b4d-4e8a-9c2f-5d6e7f8a9b0c",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('DELETE', 'https://chat.talkward.app/api/v1/webhooks/3f2a9c1e-7b4d-4e8a-9c2f-5d6e7f8a9b0c', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
]);
echo $res->getBody();
{
"ok": true
}
Sample payloads
/api/v1/webhooks/beispielePayloads as your webhook would receive them, built from your real conversations. Handy for setting up Make, Zapier or n8n.
Query parameters
ereignisstringEvent, default
nachricht_neulimitinteger1 to 10, default 3
curl "https://chat.talkward.app/api/v1/webhooks/beispiele?ereignis=nachricht_neu&limit=3" \
-H "Authorization: Bearer $TALKWARD_API_KEY"
const res = await fetch('https://chat.talkward.app/api/v1/webhooks/beispiele?ereignis=nachricht_neu&limit=3', {
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
},
});
const daten = await res.json();
import os, requests
res = requests.get(
"https://chat.talkward.app/api/v1/webhooks/beispiele",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
params={
"ereignis": "nachricht_neu",
"limit": 3,
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://chat.talkward.app/api/v1/webhooks/beispiele', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'query' => [
'ereignis' => 'nachricht_neu',
'limit' => 3,
],
]);
echo $res->getBody();
{
"ok": true,
"beispiele": [
{
"id": 88,
"ereignis": "nachricht_neu",
"zeit": "2026-09-25T09:14:00+00:00",
"gespraech": {
"…": "…"
},
"nachricht": {
"…": "…"
}
}
]
}
Delivery and signature
Talkward sends each event as a POST with JSON:
{
"id": 88,
"ereignis": "nachricht_neu",
"zeit": "2026-09-25T09:14:00+00:00",
"gespraech": {
"id": 101,
"…": "…"
},
"nachricht": {
"id": 5012,
"von": "kunde",
"text": "Where is my order?",
"…": "…"
}
}
Depending on the event, these are added: nachricht (for nachricht_neu, nachricht_gesendet and notiz_neu), zugewiesen (login, for zuweisung), abteilung (for abteilung_zugewiesen), tags_neu (for tag), vorher and grund (previous status and reason, for uebergabe, erledigt, wieder_offen and spam), meldung (for meldung_neu). The three contact events carry the kontakt instead of gespraech, as it was at the time of the event (for kontakt_geloescht that is before deletion).
Every delivery carries the headers X-Talkward-Ereignis (event), X-Talkward-Zustellung (unique delivery number) and X-Talkward-Signatur (signature). The signature is sha256= followed by the HMAC-SHA256 of the body with the geheimnis from the response when creating the webhook. This is how you check that the call comes from Talkward:
import hashlib, hmac
expected = "sha256=" + hmac.new(secret.encode(), body_bytes, hashlib.sha256).hexdigest()
genuine = hmac.compare_digest(expected, request.headers["X-Talkward-Signatur"])
Respond within 10 seconds with a 2xx status. Otherwise Talkward retries after 1, 5 and 30 minutes and after 2 hours. If you respond with 410, Talkward ends the webhook immediately; the same happens after 50 failures in a row. You can also see and end active webhooks under Settings › Add-ons › API.
Team chat and alerts
Post to a team channel
/api/v1/team/nachrichtYour system posts as a bot to a channel of the team chat. All members get a notification in the Talkward app. The channel must already exist in the team chat. The response names geraete, the number of devices that received the notification. Talkward still accepts the same message at POST https://chat.talkward.app/api/integration/nachricht.
Body
kanalstringRequiredChannel name, e.g.
qmtextstringRequiredMessage text
titelstringNotification title
linkstringTapping the notification opens this page
dringendbooleantruealso reaches muted members
curl -X POST "https://chat.talkward.app/api/v1/team/nachricht" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"kanal": "qm",
"titel": "Weighing due",
"text": "Weigh batch 4711",
"dringend": true
}'
const res = await fetch('https://chat.talkward.app/api/v1/team/nachricht', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"kanal": "qm",
"titel": "Weighing due",
"text": "Weigh batch 4711",
"dringend": true
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/team/nachricht",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"kanal": "qm",
"titel": "Weighing due",
"text": "Weigh batch 4711",
"dringend": True,
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/team/nachricht', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'kanal' => 'qm',
'titel' => 'Weighing due',
'text' => 'Weigh batch 4711',
'dringend' => true,
],
]);
echo $res->getBody();
{
"ok": true,
"geraete": 4
}
Alerts from machines, sensors and servers
/api/v1/meldungenYour system reports an event, for example a machine failure, a water sensor or a server outage. Each alert becomes a conversation in the "Alert" channel and starts automations with the trigger "Alert via API". Whether it becomes a critical alarm is up to your automation (Critical Alerts add-on). Talkward is not a certified alarm system and not an emergency call centre.
Body
titelstringRequiredShort title, at most 200 characters
textstringDescription
quellestringDevice or system, e.g.
Water sensor warehouse; defaults to the key nameschwerestringSeverity:
info,warnung(warning, default) orkritisch(critical)schluesselstringAlerts from the same
quellewith the same key go to the same open conversationmarkestringBrand (
key); without it, the first branddatenobjectValues for the automation, available there as
{{ereignis.daten.NAME}}
curl -X POST "https://chat.talkward.app/api/v1/meldungen" \
-H "Authorization: Bearer $TALKWARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"titel": "Water in the basement",
"quelle": "Water sensor warehouse",
"schwere": "kritisch",
"schluessel": "basement",
"daten": {
"level_cm": 3
}
}'
const res = await fetch('https://chat.talkward.app/api/v1/meldungen', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TALKWARD_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"titel": "Water in the basement",
"quelle": "Water sensor warehouse",
"schwere": "kritisch",
"schluessel": "basement",
"daten": {
"level_cm": 3
}
}),
});
const daten = await res.json();
import os, requests
res = requests.post(
"https://chat.talkward.app/api/v1/meldungen",
headers={"Authorization": f"Bearer {os.environ['TALKWARD_API_KEY']}"},
json={
"titel": "Water in the basement",
"quelle": "Water sensor warehouse",
"schwere": "kritisch",
"schluessel": "basement",
"daten": {
"level_cm": 3,
},
},
)
print(res.json())
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://chat.talkward.app/api/v1/meldungen', [
'headers' => ['Authorization' => 'Bearer ' . getenv('TALKWARD_API_KEY')],
'json' => [
'titel' => 'Water in the basement',
'quelle' => 'Water sensor warehouse',
'schwere' => 'kritisch',
'schluessel' => 'basement',
'daten' => [
'level_cm' => 3,
],
],
]);
echo $res->getBody();
{
"ok": true,
"neu": true,
"gespraech": {
"id": 130,
"kanal": "meldung",
"…": "…"
}
}