Skip to main content
Register an HTTPS URL with POST /api/webhooks and we send it a POST every time a post publishes. Save the secret from the response: it is shown once and is what you verify deliveries with.

What we send

Answer with any 2xx within 10 seconds. Anything else (or no answer) is retried up to two more times, 2 and 4 seconds apart. Redirects are not followed. Every attempt is listed by GET /api/webhooks/{webhook_id}/deliveries.

Verify the signature

X-Marky-Signature is sha256= followed by the hex HMAC-SHA256, keyed with your webhook secret, of:
Two rules make this safe:
  1. Use the raw body bytes. HMAC the body exactly as received, before any JSON parsing. Re-serializing the JSON changes the bytes and the check fails.
  2. Reject old timestamps. The timestamp is part of what is signed, so it cannot be altered. Refuse anything more than 5 minutes from your clock, so a captured delivery cannot be replayed later. Each retry is signed with a fresh timestamp.
Compare signatures in constant time.

Which URLs are allowed

The URL must use https:// and its hostname must resolve only to public internet addresses. Private networks (10.x, 192.168.x, 172.16-31.x), loopback, link-local and cloud-metadata addresses are refused with 400 when you register. We resolve the hostname again on every delivery and refuse to connect if it has since moved to a private address; that attempt is logged as blocked and not retried.