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

EventWhen
post.publishedA post went live on one platform. data has post_id, platform_post_id, platform, url, published_at.
post.failedA 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_reconnectA 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 https URL (no IP addresses, no custom port, no credentials in the URL).
  • Answer with any 2xx status within about 30 seconds. Do the heavy work afterwards.
  • Treat deliveries as at-least-once: use the event id to 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.