Webhooks
Webhooks are heliumOS's outbound async channel. Register an HTTPS endpoint in the dashboard, tell us which events you care about, and we'll POST each event to you. Deliveries are signed, retried, and replayable.
Registration
Webhook endpoints are registered from the operator dashboard, not via the API. Operator API keys can't mint or delete endpoints — that's a deliberate security boundary so a compromised integration key can't redirect your event stream.
In the dashboard:
- Open Settings → Webhook endpoints in the operator workspace.
- Click Add endpoint, paste your receive URL, and select the
events you want (
subscription.*,sim.*, etc.). - Save. The dashboard shows the signing secret (
whsec_...) once — copy it into your backend's secret store.
Endpoints are scoped to the dashboard's currently-selected environment. Your sandbox endpoint and live endpoint are separate records with separate signing secrets.
URL requirements
Your receive URL must be https and must resolve to a public
address — in sandbox as well as live. Endpoints on http, on a
loopback or private address (http://localhost:4000,
https://10.0.0.5/hook), on an internal hostname (.internal,
.local, a bare service name), or with credentials in the URL
(https://user:pass@host/) are refused when you save them, with a
message saying which rule applied.
The same check runs again immediately before every delivery, so an endpoint whose DNS record later moves to a private address stops receiving events rather than being delivered to. When that happens the delivery is recorded as failed on the endpoint's deliveries list with the reason, so it's visible without contacting support.
Developing against a receiver on your own machine? Put a tunnel
(ngrok, cloudflared) in front of it and register the tunnel's
https URL.
Signature verification
Every delivery carries Platform-Signature: t=<ts>,v1=<hex>. The
signed payload is <ts>.<raw-body>, HMAC-SHA256, keyed on the
signing secret. Reject requests where:
- The timestamp is older than 5 minutes (replay protection).
- The computed signature doesn't match
v1. - The event's
livemodedoesn't match the endpoint's mode.
Retries & dead-letter
Failed deliveries retry with exponential backoff (30s, 2m, 10m, 30m, 1h, 2h, 6h, 12h, 24h — 9 total attempts over ~48h). After the ninth, the event lands in the dead-letter queue, viewable in the dashboard's event stream and replayable with one click — there is no operator-key API for replay, replay is a dashboard-only action.
Ordering
Delivery is not ordered. If two events land milliseconds apart, they may be delivered out of order. Keep your handlers idempotent and resolve state from the event payload rather than assumed sequence.