Skip to content

Webhooks

Admins can add endpoints in Settings › Webhooks. HostEdge POSTs JSON to them when subscribed events happen.

Events#

EventWhen
deployment.readyA deployment finished and is live
deployment.failedA deployment failed
domain.verifiedA custom domain's DNS and certificate are active
project.createdA project was created
project.deletedA project was deleted
form.submittedA form on a project received a submission

Send test delivers a ping event.

Payload#

{
  "id": "evt_01m4…",
  "type": "deployment.ready",
  "createdAt": "2026-10-07T12:00:00.000Z",
  "workspace": { "id": "wsp_…", "slug": "acme" },
  "data": { "deployment": { "id": "dep_…", "url": "https://…" }, "project": { "slug": "shop" } }
}

Headers: X-HostEdge-Event, X-HostEdge-Delivery (unique per delivery) and X-HostEdge-Signature.

Verifying signatures#

X-HostEdge-Signature is t=<unix seconds>,v1=<hex>, where the hex is HMAC-SHA256 of "<t>.<raw body>" with your endpoint's signing secret. Reject old timestamps to stop replays.

import { createHmac, timingSafeEqual } from 'node:crypto'

export function verify(secret, rawBody, header, toleranceSeconds = 300) {
  const { t, v1 } = Object.fromEntries(header.split(',').map((p) => p.split('=')))
  if (Math.abs(Date.now() / 1000 - Number(t)) > toleranceSeconds) return false
  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex')
  return v1.length === expected.length && timingSafeEqual(Buffer.from(v1), Buffer.from(expected))
}

Retries#

Answer with any 2xx within 10 seconds. Otherwise HostEdge retries after 30 seconds, 2 minutes, 10 minutes, 1 hour and 6 hours, then marks the delivery failed. Every attempt is in the delivery log with the status code and the start of your response, and you can redeliver any event.

If every delivery to an endpoint fails for 3 days, with no success in between, HostEdge turns the endpoint off, stops retrying, and tells the workspace’s Admins in the dashboard and by email. Fix the endpoint, switch it back on, and redeliver what you missed from the log.

View this page as MarkdownAll docs as one file