Webhooks
Signed event deliveries when a scheduled post reaches a terminal state.
Register webhook endpoints in the dashboard under Settings → API Keys → Webhooks (webhook management is dashboard-only, not reachable with an API key). XreplyAI POSTs a JSON payload to your HTTPS endpoint when a scheduled post reaches a terminal state. Up to 5 webhooks per account.
Events
| Event | Fires when |
|---|---|
post.published | Every target platform published successfully. |
post.failed | Every target platform failed. |
post.partial_failure | Some platforms published, some failed. |
A test delivery (webhook.test) can be fired from the dashboard at any time.
Payload
{
"id": "b3f1e2a0-1c2d-4e5f-8a9b-0c1d2e3f4a5b",
"event": "post.published",
"post_id": 123,
"occurred_at": "2026-07-14T09:00:12Z",
"data": {
"status": "posted",
"platforms": [
{ "platform": "twitter", "platform_status": "posted",
"platform_post_id": "1811223344556677889", "platform_error": null }
]
}
}The id field is a UUID generated once when the delivery is created and
frozen into the stored payload, so it stays identical across every retry or
manual redelivery of that event. Use it as a dedupe key on your end (e.g. an
insert against a unique index on id), since the same event can otherwise
arrive more than once.
Signatures and headers
Every delivery carries an
X-XReplyAI-Signature: t=<unix-timestamp>,v1=<hex-digest> header, where the
digest is HMAC-SHA256(secret, "<t>.<raw-request-body>") using the webhook's
secret (shown once, at creation). Verify by recomputing the digest and
comparing with a constant-time comparison; reject stale timestamps (e.g.
older than 5 minutes) to prevent replay.
Two additional headers ride along on every attempt:
X-XReplyAI-Event-Id: the same dedupe key as the payload'sid, readable without parsing the bodyX-XReplyAI-Attempt: starts at1, increments on each retry or manual redelivery
Delivery policy
Endpoints must be HTTPS and respond 2xx within 5 seconds. Failed deliveries are retried up to 7 times, with waits of 10s, 100s, 15m, 1h, 2h, then 3h between attempts (about 6.5 hours from first attempt to final exhaustion). After 10 consecutive failed events a webhook is automatically disabled; re-enable it from the dashboard. The dashboard also exposes a per-delivery log (status, attempt count, last error) and manual redelivery of any individual delivery.