Getting Started·4 min read·

How do webhooks work in VeloCMS?

Webhooks are outbound HTTP POST notifications that VeloCMS sends to external services when events happen — here is the payload structure, security signature, and delivery guarantees.

A VeloCMS webhook is an outbound HTTP POST request sent to a URL you register whenever a specific event happens in your blog — like a new post being published, a new subscriber joining, or an order completing. The request body is a JSON object and the request includes an HMAC-SHA256 signature header so your receiving server can verify the request came from VeloCMS.

What does the webhook JSON payload look like?

Every webhook payload follows a consistent envelope structure: an event field (the event type like 'post.published'), a timestamp (ISO 8601 UTC), an id (a unique delivery ID for idempotency), and a data object containing the event-specific fields. For a post.published event the data object contains slug, title, url, excerpt, author.name, published_at, and tags (an array of tag names). For subscriber.created it contains email, plan, and created_at. The full JSON schema for each event type is documented in the VeloCMS API reference.

How do I verify that a webhook came from VeloCMS?

Every webhook request includes an X-VeloCMS-Signature header containing an HMAC-SHA256 hex digest of the raw request body, computed using your webhook endpoint's secret key. To verify: in your receiving server, compute HMAC-SHA256 of the raw request body using your secret key, and compare the result to the value in the header. If they match, the request is genuine. If they don't match, reject it with a 401 status. The secret key is shown once when you create the webhook endpoint — store it securely because VeloCMS can't show it again (though you can rotate it from the integrations panel anytime).

What HTTP status should my server return?

Return any 2xx status (200, 201, 204) within 10 seconds to acknowledge receipt. VeloCMS considers the delivery successful as soon as it receives any 2xx response — it doesn't parse your response body. If your processing takes longer than 10 seconds, the correct approach is to acknowledge receipt immediately with a 200 OK, then process the payload asynchronously in the background. Returning a 5xx error or letting the connection time out triggers VeloCMS's retry logic (up to 4 attempts with exponential backoff). Returning a 4xx error (like 400 Bad Request) marks the delivery as permanently failed without retrying.

Can I test webhook deliveries without publishing a real post?

Yes. In Admin → Settings → Integrations → Webhooks, each registered endpoint has a Send Test Event button. Clicking it sends a sample payload of the selected event type to your endpoint URL immediately, using the same signature header as a real event. This lets you verify your receiving server's signature check and response handling without needing to create real content. The test event payload is clearly marked with a 'test': true flag in the JSON so your server can skip processing if it's not ready for test events yet.

The delivery ID in the webhook envelope (the 'id' field) is stable across retries — the same event always gets the same delivery ID. Use this for idempotency checks in your receiving server: store received delivery IDs and skip processing if you've already handled that ID. This prevents duplicate side effects if VeloCMS retries a delivery your server already processed.