curl -X POST https://tawked.com/v1/webhooks \
-H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.acme.sa/tawked",
"events": [
"email.delivered",
"email.bounced",
"email.complained",
"email.failed"
]
}'const res = await fetch("https://tawked.com/v1/webhooks", {
method: "POST",
headers: {
Authorization: "Bearer tk_live_xxxxxxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
"url": "https://hooks.acme.sa/tawked",
"events": [
"email.delivered",
"email.bounced",
"email.complained",
"email.failed"
]
}),
});
const data = await res.json();<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://tawked.com/v1/webhooks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'url' => '<string>',
'events' => '<array>',
'receives_test' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}import requests
res = requests.post(
"https://tawked.com/v1/webhooks",
headers={"Authorization": "Bearer tk_live_xxxxxxxxxxxxxxxxxxxx"},
json={
"url": "https://hooks.acme.sa/tawked",
"events": [
"email.delivered",
"email.bounced",
"email.complained",
"email.failed"
]
},
)
data = res.json(){
"id": "0199f210-4e5f-7a6b-8c7d-8e9f0a1b2c34",
"url": "https://hooks.acme.sa/tawked",
"events": [
"email.delivered",
"email.bounced",
"email.complained",
"email.failed"
],
"enabled": true,
"state": "receiving",
"disabled_reason": null,
"failing_since": null,
"receives_test": false,
"last_delivery": null,
"signing": {
"schemes": [
"tawked",
"standard_webhooks"
],
"standard_since": "2026-10-23T08:00:00+00:00",
"previous_valid_until": null
},
"created_at": "2026-10-23T08:00:00+00:00",
"updated_at": "2026-10-23T08:00:00+00:00",
"secrets": {
"standard": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw",
"tawked": "whk_7a1c2f9e0b3d4c5a6e7f8091a2b3c4d5"
}
}Create a webhook endpoint
Adds an endpoint, signed with both schemes, and answers its two secrets once: the Tawked secret and the Standard Webhooks whsec_ secret. Without events it receives the application’s products’ events except the ones each owner adds by name: email.sent, email.delivery_delayed, email.suppressed, email.scheduled, email.canceled, email.opened, email.clicked, domain.* and suppression.*. A live key of the application with the explicit webhooks:manage: a full-access key does not hold it.
curl -X POST https://tawked.com/v1/webhooks \
-H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.acme.sa/tawked",
"events": [
"email.delivered",
"email.bounced",
"email.complained",
"email.failed"
]
}'const res = await fetch("https://tawked.com/v1/webhooks", {
method: "POST",
headers: {
Authorization: "Bearer tk_live_xxxxxxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
"url": "https://hooks.acme.sa/tawked",
"events": [
"email.delivered",
"email.bounced",
"email.complained",
"email.failed"
]
}),
});
const data = await res.json();<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://tawked.com/v1/webhooks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'url' => '<string>',
'events' => '<array>',
'receives_test' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}import requests
res = requests.post(
"https://tawked.com/v1/webhooks",
headers={"Authorization": "Bearer tk_live_xxxxxxxxxxxxxxxxxxxx"},
json={
"url": "https://hooks.acme.sa/tawked",
"events": [
"email.delivered",
"email.bounced",
"email.complained",
"email.failed"
]
},
)
data = res.json(){
"id": "0199f210-4e5f-7a6b-8c7d-8e9f0a1b2c34",
"url": "https://hooks.acme.sa/tawked",
"events": [
"email.delivered",
"email.bounced",
"email.complained",
"email.failed"
],
"enabled": true,
"state": "receiving",
"disabled_reason": null,
"failing_since": null,
"receives_test": false,
"last_delivery": null,
"signing": {
"schemes": [
"tawked",
"standard_webhooks"
],
"standard_since": "2026-10-23T08:00:00+00:00",
"previous_valid_until": null
},
"created_at": "2026-10-23T08:00:00+00:00",
"updated_at": "2026-10-23T08:00:00+00:00",
"secrets": {
"standard": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw",
"tawked": "whk_7a1c2f9e0b3d4c5a6e7f8091a2b3c4d5"
}
}Authorizations
Authorization: Bearer . An application key (tk_live_, tk_test_) has full access, which covers every product and any product added later, or custom access, chosen when the key is created: one or more of the scopes verify:check, verify:send (includes verify:check), notifications:read, notifications:send (includes notifications:read), email:read, email:send (includes email:read), email:manage (includes email:send), webhooks:manage, email:inbound, notifications:templates (includes notifications:read), chat:menus, chat:attendant. No key made on the API keys page holds notifications:templates, full access included: the three template writes answer such a key 403 insufficient_scope. A connected app's key holds it. Nor chat:menus: the five conversation menu operations answer such a key 403 insufficient_scope, and a connected app's key holds it once the client approved it. Nor chat:attendant: the five auto-attendant operations answer such a key 403 insufficient_scope too, and a connected app's key holds it once the client approved it. email:manage and webhooks:manage are held only by a key someone chose them for: a full-access key, old or new, never holds them. email:inbound, which reads, deletes and forwards received e-mail, is opt-in on every key, full access included: a key holds it only when it was turned on when the key was created. A call outside the key's access answers 403 insufficient_scope and names the scope it needs in the WWW-Authenticate response header. A partner key (tk_partner_) always has full access. Whatever its access, a key is a server-side secret.
Headers
Up to 128 characters. A retry with the same key and the same body within 24 hours answers what the first call answered and changes nothing again; the same key with another body answers 409 idempotency_key_reused.
Body
Response
Created