Overview
Webhooks push every Punch Rescue event to an HTTP endpoint you control, in real time. The moment an emergency is declared, re-categorized, or resolved — or a device goes offline, comes back, loses power, or fails over — Rescue fans the event out to the base-station devices in the org and to every registered webhook subscriber whose scope covers that org. Every delivery uses the same stable JSON envelope — thePublicWebhookEnvelope — regardless of event type, so you write one parser and switch on eventType.
Webhook subscriptions are registered by a Punch Rescue Admin portal, not through the Public API — there’s no public CRUD for subscriptions in v1. Tell your Punch Rescue contact the URL to call, which events you want, and the partner / enterprise / org scope, and they’ll provision it. Everything on this page describes what you’ll receive once a subscription exists.
How a subscription is scoped
A single subscription can cover one org or thousands. Your Rescue admin configures these knobs at registration:
Because the subject can span many orgs, always route on the envelope’s
orgId — it’s the org the event actually happened in, not the subscription’s subject.
The delivery envelope
Every webhook is an HTTPPOST with this top-level JSON body. Only data varies by event type.
Event types
A subscription receives only the event types it was registered for. Today’s catalog:The catalog grows additively. New event types can appear within your
apiVersion — ignore any eventType you don’t recognize rather than erroring.Emergency data
Payload for the emergency.* events.
Device data
Payload for the device.* events.
Delivery semantics
- Transport. HTTP
POSTto your subscription URL with the JSON envelope as the body andContent-Type: application/json. - Headers. Every request carries
Content-Type: application/jsonandUser-Agent: Rescue-Webhook/1.0, plus any custom headers configured on your subscription. (Custom headers can’t override those two reserved names.) - Timeout. Rescue waits up to 10 seconds for your response. Respond fast — do the real work asynchronously after acking.
- Success. Any
2xxmarks the delivery succeeded. - At-least-once. Fan-out is asynchronous and retried, so you may receive the same event more than once. Make your handler idempotent (see below).
Retries & auto-disable
Ordering & idempotency
- Dedup on
eventId. The sameeventIdis sent to every subscription for a given event and is your dedup key. Do not dedup ondeliveryId— that’s unique per attempt and changes on retry. - Order on
(entity, sequence). Deliveries can arrive out of order. Usesequenceto order events for the same entity:
eventId, drops duplicates, and never lets a lower sequence overwrite committed state for the same entity.
Securing your endpoint
- Shared-secret header. Ask your Rescue admin to attach a secret header to your subscription (e.g.
X-Webhook-Token: <random>) and reject any request that doesn’t carry the expected value. Header values are write-only — after registration only the header names are visible, so a leaked subscription record can’t reveal the secret. - HTTPS only. Serve the endpoint over TLS so the secret header and payload aren’t sent in the clear.
- Validate what you receive. Confirm
orgIdis one you expect andeventTypeis one you handle before acting on a delivery. - Don’t trust the network alone. Combine the secret header with allow-listing Rescue’s egress where your infrastructure supports it.
Testing your endpoint
Rescue can fire a syntheticwebhook.ping at your subscription so you can confirm reachability, auth headers, and parsing before any real event flows. Ask your Rescue admin to trigger a ping (for partner/enterprise subscriptions they pick which orgId the synthetic envelope carries). You’ll receive a standard envelope:
2xx and you’re wired up.
Versioning
apiVersion is date-versioned (YYYY-MM-DD) and pinned at subscription creation. The current version is 2026-05-01.
- Additive changes ship within a version — new fields and new event types can appear without a version bump. Build tolerantly: ignore unknown fields and unknown
eventTypes. - Breaking changes ship a new
apiVersion. Old versions keep flowing to subscriptions pinned to them until you migrate, so an upgrade is never forced on you mid-integration.
Best practices
Ack fast, process later
Ack fast, process later
Return
2xx within the 10-second window, then do the heavy lifting (DB writes, downstream calls) asynchronously. Slow handlers get treated as timeouts and retried.Make handlers idempotent
Make handlers idempotent
Delivery is at-least-once. Dedup on
eventId and design writes so re-processing the same event is a no-op.Order with sequence, not arrival time
Order with sequence, not arrival time
Never assume
declared arrives before resolved. Order on (emergencyId, sequence) / (deviceId, sequence) and ignore stale, lower-sequence updates.Tolerate growth
Tolerate growth
New event types and new
data fields can appear within your apiVersion. Switch on known eventTypes and ignore the rest instead of erroring.Keep your endpoint healthy
Keep your endpoint healthy
Ten consecutive failures auto-disable the subscription. Monitor your
2xx rate and return 5xx (not 4xx) for transient problems so Rescue retries instead of giving up.