Webhooks push events to your server so you don’t have to poll. They’re the reliable way to learn the outcome of scheduled posts and asynchronous (video) uploads.
Subscribe
curl -X POST https://api.madiad.com/v1/webhooks \
-H "Authorization: Bearer $MADIAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/madiad-webhook",
"events": ["post.published", "post.failed"]
}'
The response includes a secret — store it. You’ll use it to verify every delivery.
Events
| Event | Fires when |
|---|
post.published | A post (immediate or scheduled) goes live on a platform |
post.failed | A platform rejects the post |
Each delivery is a JSON body describing the post, the platform, and the result.
Verify the signature
Every request carries an X-MADIAD-Signature header: an HMAC-SHA256 of the raw request body, keyed with your subscription secret. Recompute it and compare before trusting the payload.
import crypto from "node:crypto";
function verify(rawBody, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected),
);
}
Verify against the raw, unparsed body. Re-serializing parsed JSON changes the bytes and the signature will not match.
Respond and retries
- Return a
2xx status quickly (within a few seconds) to acknowledge receipt.
- Any non-
2xx response or a timeout is retried with exponential backoff.
- Make your handler idempotent — a delivery can arrive more than once. Dedupe on the event or post
id.
Do slow work (database writes, downstream calls) after you respond 2xx — for example by enqueueing the event — so you never trip the delivery timeout.