API
Webhooks
Get a signed HTTPS request when a post is published or fails, and verify it.
Instead of polling GET /posts/:id/results, register an endpoint and CreatorHyve calls it when something happens. Add endpoints under Settings, then Developer, then Webhooks, or with POST /webhooks.
Events
| Event | When |
|---|---|
post.published | A post went live on one platform. data has post_id, platform_post_id, platform, url, published_at. |
post.failed | A post could not be published and will not be retried automatically. data has post_id, platform_post_id, platform and error (code, message, action). |
account.needs_reconnect | A connected account lost access and must be reconnected. data has account_id, platform, username. Sent once per failure. |
Every delivery is a POST with a JSON body:
{
"id": "evt_7f0c3a52-0c93-4f4f-9a2e-0b1f5f6d2a10",
"type": "post.published",
"created_at": "2030-01-15T09:00:04.512Z",
"data": {
"post_id": "c8f1e4b2-...",
"platform_post_id": "a3d2...",
"platform": "bluesky",
"url": "https://bsky.app/profile/you.bsky.social/post/3k...",
"published_at": "2030-01-15T09:00:04.100Z"
}
}
Requirements for your endpoint
- A public
httpsURL (no IP addresses, no custom port, no credentials in the URL). - Answer with any
2xxstatus within about 30 seconds. Do the heavy work afterwards. - Treat deliveries as at-least-once: use the event
idto ignore repeats.
Verifying the signature
Each delivery carries X-CreatorHyve-Signature: t=<unix seconds>,v1=<hex>. The v1 value is the HMAC-SHA256 of "<t>.<raw body>" with your endpoint's signing secret (whsec_..., shown once when you create the endpoint). Reject deliveries whose timestamp is more than five minutes old.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(secret, rawBody, header) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const expected = createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest();
const given = Buffer.from(parts.v1, "hex");
return given.length === expected.length && timingSafeEqual(given, expected);
}
import hmac, hashlib, time
def verify(secret: str, raw_body: bytes, header: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
if abs(time.time() - int(parts["t"])) > 300:
return False
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"])
Verify against the raw request body, before any JSON parsing.
Retries
If your endpoint does not answer 2xx, CreatorHyve retries after 1 minute, 5 minutes and 30 minutes, then gives up on that delivery. An endpoint that keeps failing is paused after 10 failed deliveries; resume it in the dashboard once it is fixed. Use the Test button (or POST /webhooks/:id/test) to send a webhook.test event.