# tawk.to Webhooks

## When to Use This Skill

* How do I receive tawk.to webhooks?
* How do I verify the `X-Tawk-Signature` header on a tawk.to webhook?
* Why is my tawk.to webhook signature verification failing?
* How do I handle `chat:start`, `chat:end`, `chat:transcript_created` and `ticket:create` events?

## Essential Code (USE THIS)

tawk.to signs every webhook with **HMAC-SHA1 over the raw request body**, keyed with the
webhook's secret key. The lowercase hex
digest is sent in the `X-Tawk-Signature` header. There is no timestamp and no prefix.

### Verification (core)

```javascript
const crypto = require('crypto');

function verifyTawkSignature(rawBody, signatureHeader, secret) {
  if (!signatureHeader || !secret) return false;
  const expected = crypto.createHmac('sha1', secret).update(rawBody).digest('hex');
  const a = Buffer.from(signatureHeader, 'utf8');
  const b = Buffer.from(expected, 'utf8');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

```

```python
import hashlib, hmac

def verify_tawk_signature(raw_body: bytes, signature: str | None, secret: str) -> bool:
    if not signature or not secret:
        return False
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha1).hexdigest()
    return hmac.compare_digest(signature.encode(), expected.encode())

```

**Use the raw body.** In Express, mount `express.raw({ type: '*/*' })` on the route so verification
works whatever `Content-Type` the request carries; parse JSON only after the signature checks out.

> **For complete handlers with tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/tawk-to-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/tawk-to-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/tawk-to-webhooks/examples/fastapi/).

## Common Event Types

The event name is in the payload's `event` field (tawk.to sends no event-type header).

| Event | Triggered When |
| --- | --- |
| `chat:start` | The first message of a chat is sent by a visitor or agent (whispers and system messages don't count) |
| `chat:end` | A chat has ended |
| `chat:transcript_created` | The full transcript is generated after a chat session ends |
| `ticket:create` | A new ticket is created |

Each delivery carries an `X-Hook-Event-Id` header that stays the same across retries: use it
as your idempotency key. Respond with any 2XX within 30 seconds; failures are retried for up to 12 hours.

## Environment Variables

```bash
# The webhook's secret key (webhooks are under Administration > Settings > Webhooks)
TAWK_WEBHOOK_SECRET=your_webhook_secret_key

```

## Local Development

```bash
npx hookdeck-cli listen 3000 tawk-to --path /webhooks/tawk-to

```

No account required. Use the URL Hookdeck prints as the webhook URL in tawk.to.

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/tawk-to-webhooks/references/overview.md) - What tawk.to webhooks are, events and payloads
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/tawk-to-webhooks/references/setup.md) - Create a webhook and get the secret key
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/tawk-to-webhooks/references/verification.md) - HMAC-SHA1 verification details and gotchas