Guides
Webhooks
Subscribe to FeedHorizon events and verify deliveries securely.
Overview
Webhooks let FeedHorizon push real-time event notifications to your application.
Common use cases:
- Mark posts as published in your internal system
- Alert on failed publishing attempts
- Trigger downstream automation when accounts connect or disconnect
Supported events
You can subscribe to one or more of the following events:
post.scheduledpost.publishedpost.failedpost.partialaccount.connectedaccount.disconnectedmessage.receivedcomment.received
Create a webhook
curl -X POST https://app.feedhorizon.dev/api/v1/webhooks \
-H "Authorization: Bearer fh_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Production endpoint",
"url": "https://api.example.com/webhooks/feedhorizon",
"events": ["post.published", "post.failed"]
}'Response includes your webhook record and signing secret (whsec_...).
Delivery format
FeedHorizon sends POST requests with a JSON payload:
{
"event": "post.published",
"timestamp": "2026-03-09T10:20:30.000Z",
"data": {
"id": "clxyz...",
"status": "PUBLISHED"
}
}Verify signatures (HMAC-SHA256)
Each webhook request includes:
X-Webhook-Signature- lowercase hex HMAC SHA-256 digestX-Webhook-Event- event name
Compute the HMAC using your webhook secret and the raw request body, then compare it to X-Webhook-Signature.
import crypto from 'crypto';
export function verifyFeedHorizonSignature(rawBody, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected, 'utf8'),
Buffer.from(signature || '', 'utf8'),
);
}Test a webhook endpoint
You can trigger a manual test delivery:
curl -X POST https://app.feedhorizon.dev/api/v1/webhooks/WEBHOOK_ID/test \
-H "Authorization: Bearer fh_YOUR_API_KEY"Test deliveries use event webhook.test.
Failure handling
- FeedHorizon records each attempt in webhook logs
- Delivery timeout is 10 seconds
- On success,
failCountresets to0 - After 10 consecutive failures, the webhook is automatically disabled (
isActive = false)
Best practices
- Return
2xxquickly, then process asynchronously - Keep endpoint idempotent (duplicate deliveries are possible)
- Store and rotate secrets periodically
- Restrict webhook endpoint access with network controls and signature checks