Reference sheet · lesson 3

tawk.to webhooks

Four events, one signature, one retry policy. Everything from the developer page, compressed.tawk.to webhooks reference

Events and fields

eventWhenPayload
chat:startFirst message by visitor or agent (not whispers or trigger notifications)chatId, time, domain, referrer, message{ text, type: msg|file|webrtc-call, sender{ type: agent|visitor|system } }, visitor{ name, email?, city, country }, property{ id, name }
chat:endChat endedchatId, time, domain, referrer, visitor, property
chat:transcript_createdAfter all chats in a session ended + 3 minutes of inactivitytime, domain, referrer, chat{ id, visitor, messages[{ sender{ t: a|v|s, n?, id? }, type, msg?, time, attchs?[{ type, content.file{ url, name, mimeType, size, extension } }] }] }, property
ticket:createNew tickettime, property, requester{ name, email, type? }, ticket{ id, humanId, subject, message }

sender.t: a agent, v visitor, s system. No per-message event exists. Custom attributes and tags are not in any payload.

Signature

import { createHmac, timingSafeEqual } from "node:crypto";
const expected = Buffer.from(createHmac("sha1", secret).update(rawBody).digest("hex"), "hex");
const given = Buffer.from(header ?? "", "hex");
const ok = given.length === expected.length && given.length > 0 && timingSafeEqual(given, expected);

Retries

Dashboard

Administration → Settings → Webhooks → Create Webhook: name, HTTPS endpoint URL, events. Up to 10 webhooks per property. Enable/disable, edit, delete from the list.tawk.to Help: creating and managing webhooks

Vercel handler (examples/api/tawk-webhook.ts)

export async function POST(request: Request) {
  const rawBody = await request.text();
  const result = await handleTawkWebhook(
    { rawBody, signature: request.headers.get("x-tawk-signature"), eventId: request.headers.get("x-hook-event-id") },
    { secret: process.env.TAWK_WEBHOOK_SECRET ?? "", store },
  );
  return new Response(result.body, { status: result.status });
}

Order inside handleTawkWebhook: secret present → verify (401) → parse (400) → dedupe (200 duplicate) → store → side effects → 200 ok <event>.

Test from your machine

cd examples
npx tsx scripts/send-test-webhook.ts https://your-app.vercel.app/api/tawk-webhook "$TAWK_WEBHOOK_SECRET" chat:transcript_created --id t1
npx tsx scripts/send-test-webhook.ts https://your-app.vercel.app/api/tawk-webhook "$TAWK_WEBHOOK_SECRET" chat:start --tamper