Skip to content

How to set up Throk webhooks: rules, payload format and signature verification

Webhooks save you from polling the API. Set up rules, and when a matching post appears on Threads, Throk sends the post data as a POST to the URL you choose. Common uses:

  • Push to Slack, LINE or an internal system when your brand or product is mentioned and starts to gain traction
  • Watch a topic for posts whose likes, replies or views pass a threshold
  • Import posts that are going viral into your database or CRM automatically

A webhook has two parts:

  • Endpoint: the URL that receives notifications, for example https://example.com/throk-webhook. Each endpoint has its own signing secret.
  • Rule: decides which posts to send. Each rule belongs to one endpoint, and an endpoint can have several rules.

Throk checks all rules every 3 minutes. Matching posts are sent to the endpoint as one event per post. The same post is sent only once per rule.

Sends a post when its text contains your keyword and it reaches your thresholds.

  • One keyword per rule. Matching works the same as keyword search: Chinese matches character by character, English matches by word.
  • Checks posts published in the last 24 hours.
  • Set at least one threshold. The minimums are: likes ≥ 10, replies ≥ 5, views ≥ 20,000.

No keyword. Sends any post published in the chosen window that reaches your thresholds. Use it to catch content that’s going viral.

  • Checks posts published in the past 1–72 hours (set with lookbackHours).
  • Set at least one threshold. The minimums are: likes ≥ 500, replies ≥ 100, views ≥ 20,000.
  • Thresholds within one rule are combined with AND: for example likes ≥ 100 and replies ≥ 10.
  • Rules are independent: a post that matches two rules sends two events.
  • You can filter by post language: zh (all Chinese, the default), zh-Hant (Traditional Chinese), zh-Hans (Simplified Chinese), yue (Cantonese), ja (Japanese), ko (Korean). Each post’s own language decides, not where the author is; zh covers zh-Hant, zh-Hans and yue.
  • Replies are included: replies can also trigger a rule. Use the is_reply field in the event to tell them apart.
  • View thresholds trigger later: a post’s view count usually isn’t available until a few hours after it’s published, so rules with a view threshold send later than rules that only check likes and replies.
  1. Sign in to the developer portal and open Endpoints and rules.
  2. Click Add endpoint, enter your URL and click Create.
  3. Under the endpoint, click + Add rule, choose Keyword or Trending threshold, set the language and thresholds (for trending thresholds, also set how many past hours to check), then click Add.
  4. Click Test on the endpoint to confirm your server receives events. You can test any time after creating the endpoint, without adding a rule first. Test events cost no credits.
  5. Expand the endpoint to see its Signing secret, which you use to verify signatures.

The webhooks page in the developer portal: adding a keyword rule under an endpoint, with language and likes, replies and views thresholds

Every event sent and the response status from your server are listed on the Delivery log page, where you can resend failed events.

You can also manage endpoints and rules with the API. Every request needs your API key.

Method and path Purpose
GET /webhook/endpoints List your endpoints, signing secrets (secret) and rules
POST /webhook/endpoints Create an endpoint
DELETE /webhook/endpoints/{endpoint_id} Delete an endpoint (and all of its rules)
POST /webhook/endpoints/{endpoint_id}/rules Create a rule under an endpoint
DELETE /webhook/rules/{rule_id} Delete a rule
POST /webhook/endpoints/{endpoint_id}/test Send a test event (free)

Create an endpoint:

終端機視窗
curl -X POST 'https://premium-api.throk.ai/webhook/endpoints' \
-H 'Authorization: Bearer sk-throk-...' \
-H 'Content-Type: application/json' \
-d '{"url": "https://example.com/throk-webhook"}'

Create a keyword rule (Traditional Chinese posts with likes ≥ 100):

終端機視窗
curl -X POST 'https://premium-api.throk.ai/webhook/endpoints/{endpoint_id}/rules' \
-H 'Authorization: Bearer sk-throk-...' \
-H 'Content-Type: application/json' \
-d '{"keyword": "珍珠奶茶", "likeCount": 100, "language": "zh-Hant"}'

Create a trending threshold rule (posts from the past 6 hours with likes ≥ 1,000):

終端機視窗
curl -X POST 'https://premium-api.throk.ai/webhook/endpoints/{endpoint_id}/rules' \
-H 'Authorization: Bearer sk-throk-...' \
-H 'Content-Type: application/json' \
-d '{"likeCount": 1000, "lookbackHours": 6}'

Rule fields:

Field Description
keyword The keyword. Leave it out for a trending threshold rule
likeCount, replyCount, viewCount Likes, replies and views thresholds. Set at least one
lookbackHours Check posts published in the past N hours, 1–72. Required for trending threshold rules. Keyword rules always check the last 24 hours and can’t set it (returns 400)
language Post language: zh, zh-Hant, zh-Hans, yue, ja, ko (case-insensitive). Default zh. Responses always use these spellings

Field names also accept snake case, such as like_count or lookback_hours. Responses always use the names in the table above.

Rules can’t be edited. To change one, delete it and create it again (the developer portal lets you edit directly).

Each event is sent to your endpoint as a POST with a JSON body:

{
"post": {
"url": "https://threads.com/post/DXZoK1VlEvT",
"code": "DXZoK1VlEvT",
"caption": "串文內容……",
"is_reply": false,
"like_count": 1700,
"reply_count": 293,
"repost_count": 40,
"reshare_count": 180,
"impression_count": 254300,
"post_timestamp": 1776760127,
"media_url": ["https://media01.throk.ai/media/..."]
},
"user": {
"username": "throk.ai",
"full_name": "Throk|定義 Threads 數據新標準",
"profile_picture": "https://media01.throk.ai/profile/77928681697.jpg"
},
"rule": {
"id": "9b2f6c1e-…",
"type": "keyword",
"keyword": "珍珠奶茶"
}
}
  • The numbers are a snapshot at the time of sending. If the post keeps growing, no update is sent.
  • repost_count includes reposts and quotes. impression_count is null when no view data is available yet.
  • rule is the rule that triggered the event: id is the rule ID (the same one returned when you created the rule), type is keyword (keyword rule) or trending (trending threshold rule), and keyword is null for trending threshold rules. When a post matches several rules, each rule sends its own event.
  • For test events, rule is {"id": "test", "type": "test", "keyword": null}, so you can tell them apart from real events.

Every event is signed, so you can confirm the request really came from Throk and wasn’t tampered with.

  • See the signing secret by expanding the endpoint in the developer portal, or get it from the secret field in the GET /webhook/endpoints response.
  • The signature is in the X-Throk-Signature request header, in the format t=<UNIX timestamp>,v1=<signature>.
  • To verify: compute HMAC-SHA256 (hex) of <timestamp>,<raw request body> with the signing secret as the key, and compare it with v1. Also check that the timestamp is within a few minutes, to block replay attacks.

Node.js example:

import crypto from 'node:crypto';
// rawBody: the raw request body (string), header: the value of X-Throk-Signature
function verify(rawBody, header, secret) {
const fields = header.split(',').map((p) => p.split('='));
const t = Number(fields.find(([k]) => k === 't')?.[1]);
if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; // only accept requests from the last 5 minutes
const expected = Buffer.from(
crypto.createHmac('sha256', secret).update(`${t},${rawBody}`).digest('hex'),
);
// during secret rotation there may be several v1 values; any match is valid
return fields
.filter(([k]) => k === 'v1')
.some(([, sig]) => {
const got = Buffer.from(sig);
return got.length === expected.length && crypto.timingSafeEqual(got, expected);
});
}

Compute it from the raw request body. Don’t parse it as JSON and turn it back into a string first.

  • Respond with HTTP 2xx as fast as you can. Move slow work to the background.
  • Events that don’t get a 2xx response are retried automatically with exponential backoff, up to 10 times. You can also resend them by hand from the Delivery log page in the developer portal.
  • Each endpoint receives at most 1,000 events per 60 seconds. Anything over that is delayed.
  • Real events carry an X-Convoy-Idempotency-Key header (test events don’t). Its value stays the same when an event is retried, so use it (or the post’s code) to deduplicate and avoid processing an event twice.
  • Each event sent costs 20 credits, from the same account credits as API calls. The same post is charged only once per rule. The charge applies when the event is sent, whether or not your server responds successfully, so make sure your endpoint can receive events.
  • Creating and deleting endpoints and rules, and test events, cost no credits.
  • When you run out of credits, events pause. After you top up, posts still within the check window are sent in the next round.
  • If you downgrade to a plan without webhooks, your existing rules are kept but no longer trigger.
  • Webhook usage appears on the Usage page with the API type webhook.

There’s no pause switch. To stop deliveries, delete the rules or the endpoint. Deleting an endpoint also deletes all of its rules.

For an overview of webhooks and which plans include them, see Throk Webhooks.