Webhooks
Webhooks push account events to your server as they happen: a post went live, a lead was found, a DM arrived, a Worker batch is ready. They fire only on data Xholic already collects, so they never cause extra X calls. Mentions and replies arrive at your plan’s sync cadence; DMs arrive close to real time.
Prefer polling? The same events are in the events feed.
Set up an endpoint
Section titled “Set up an endpoint”In Xholic, open Settings → API / MCP / CLI → Webhooks and add an HTTPS URL. Pick the events and the X accounts it should receive (all by default). The signing secret (whsec_…) is shown there; rotate it any time. Send test event delivers a webhook.test event.
| Plan | Trial | Pro | Max | Ultra |
|---|---|---|---|---|
| Endpoints | 1 | 3 | 5 | 10 |
What arrives
Section titled “What arrives”A POST with a JSON body:
{ "id": "post.published:…", "type": "post.published", "occurred_at": "2026-10-28T14:00:03.000Z", "account": { "user_id": "…", "handle": "yourhandle" }, "data": { "post_id": "…", "tweet_id": "1850000000000000000", "tweet_url": "https://x.com/yourhandle/status/1850000000000000000", "text": "The first 280 characters of the post…", "source": "freeform", "posted_at": "2026-10-28T14:00:03.000Z" }, "api_version": "v1"}Payloads are small: IDs plus the few fields you usually need. Fetch the rest with the API (for example queue.get_post or posts.get).
| Header | Value |
|---|---|
webhook-id |
The event id. The same on every retry: use it to drop duplicates. |
webhook-timestamp |
Unix seconds of this attempt. |
webhook-signature |
v1,<base64 HMAC-SHA256>; see Verify signatures. |
content-type |
application/json |
user-agent |
Xholic-Webhooks/1 |
The format is Standard Webhooks, so any Standard Webhooks library verifies it with your whsec_ secret.
Delivery and retries
Section titled “Delivery and retries”Reply with any 2xx within 10 seconds. Anything else, a timeout or a network error counts as a failure and the delivery is retried:
| Try | When | Since the first try |
|---|---|---|
| 1 | Right away | 0 |
| 2 | 30 seconds after try 1 | about 30 seconds |
| 3 | 2 minutes after try 2 | about 2.5 minutes |
| 4 | 10 minutes after try 3 | about 12.5 minutes |
| 5 | 30 minutes after try 4 | about 42.5 minutes |
| 6 | 1 hour after try 5 | about 1.7083333333333333 hours |
| 7 | 2 hours after try 6 | about 3.7083333333333335 hours |
| 8 | 6 hours after try 7 | about 9.708333333333334 hours |
| 9 | 12 hours after try 8 | about 21.708333333333332 hours |
- Delivery is at least once: the same event can arrive twice, and events can arrive out of order. Dedupe by
webhook-idand order byoccurred_at. - An endpoint that keeps failing for 3 days is switched off and its owner is emailed. Turn it back on in Settings.
- Every delivery is logged for 30 days with its response status; Replay sends one again.
- Payloads are at most 256 KB.
Safety
Section titled “Safety”Only https:// URLs are accepted. URLs that resolve to private, loopback or link-local addresses are refused, both when you save them and before every delivery. Respond quickly and do the work in the background; a slow endpoint gets timeouts and retries.
