# TikTok Webhooks

Webhooks from the TikTok for Developers platform (developers.tiktok.com) —
Login Kit, Content Posting / Video Kit, and Data Portability. These are not
TikTok Shop webhooks, which use a different portal and signature scheme — see
[tiktok-shop-webhooks](/webhooks/skills/tiktok-shop-webhooks).

## When to Use This Skill

* How do I receive TikTok webhooks?
* How do I verify the TikTok-Signature header?
* Why is my TikTok webhook signature verification failing?
* How do I handle authorization.removed, video.upload.failed, video.publish.completed, or portability.download.ready events?
* How do I reject replayed TikTok webhook deliveries?

## Verification (core)

TikTok has no webhook SDK — verify manually. The `TikTok-Signature` header
looks like `t=1633174587,s=<hex>`. The signature is `HMAC-SHA256(client_secret, "&lt;t>.&lt;raw_body>")`, hex-encoded. Verify against the raw request body (don't
`JSON.parse` first) and reject stale timestamps to block replay.

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

function verifyTikTokWebhook(rawBody, header, clientSecret, toleranceSec = 300) {
  if (!header || !clientSecret) return false;
  const parts = Object.fromEntries(
    header.split(',').map((kv) => kv.split('='))
  );
  const { t, s } = parts;
  if (!t || !s) return false;

  // Reject stale timestamps (no tolerance window is documented; 5 min is sane).
  const age = Math.abs(Math.floor(Date.now() / 1000) - Number(t));
  if (!Number.isFinite(age) || age > toleranceSec) return false;

  const raw = Buffer.isBuffer(rawBody) ? rawBody.toString('utf8') : rawBody;
  const expected = crypto
    .createHmac('sha256', clientSecret)
    .update(`${t}.${raw}`, 'utf8')
    .digest('hex');
  try {
    return crypto.timingSafeEqual(Buffer.from(s, 'hex'), Buffer.from(expected, 'hex'));
  } catch {
    return false; // length mismatch = invalid
  }
}

```

> For complete handlers with route wiring, event dispatch, and tests, see:
> 
> * [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/tiktok-webhooks/examples/express/)
> * [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/tiktok-webhooks/examples/nextjs/)
> * [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/tiktok-webhooks/examples/fastapi/)

## Common Event Types

TikTok for Developers currently defines four webhook events:

| Event | Triggered When |
| --- | --- |
| `authorization.removed` | A user deauthorizes your app (access token already revoked) |
| `video.upload.failed` | A video uploaded via Video Kit fails to upload |
| `video.publish.completed` | A video uploaded via Video Kit is published by the user |
| `portability.download.ready` | Data requested via the Data Portability API is ready to download |

> Watch the exact names: it is `video.publish.completed` (not `.complete`),
> and there is no `video.publish.failed`. See
> [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/tiktok-webhooks/references/overview.md) for payload details.

## Payload Structure

Events are POSTed as JSON:

```json
{
  "client_key": "awx4...",
  "event": "video.publish.completed",
  "create_time": 1633174587,
  "user_openid": "0f9c...",
  "content": "{\"share_id\":\"video.7107...\"}"
}

```

`content` is a serialized JSON string — parse it separately after parsing
the envelope. `portability.download.ready` has no `user_openid`.

## Environment Variables

```bash
TIKTOK_CLIENT_SECRET=your_app_client_secret   # signs the webhook; from the developer portal

```

The webhook signing key is your app's client secret — the same secret used
for OAuth. There is no separate webhook secret.

## Local Development

```bash
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 tiktok --path /webhooks/tiktok

```

Register the printed HTTPS URL as your callback URL in the TikTok developer
portal and subscribe to events.

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/tiktok-webhooks/references/overview.md) - TikTok webhook concepts, events, payloads
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/tiktok-webhooks/references/setup.md) - Developer portal configuration
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/tiktok-webhooks/references/verification.md) - Signature verification details and gotchas