Skip to main content

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 — the PublicWebhookEnvelope — 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 HTTP POST 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 POST to your subscription URL with the JSON envelope as the body and Content-Type: application/json.
  • Headers. Every request carries Content-Type: application/json and User-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 2xx marks 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

After 10 consecutive failed deliveries, Rescue auto-disables the subscription (status flips to disabled_failure) and stops sending. A successful delivery resets the counter. Re-enabling a disabled subscription is a Rescue-admin action — reach out to your contact once your endpoint is healthy again.

Ordering & idempotency

  • Dedup on eventId. The same eventId is sent to every subscription for a given event and is your dedup key. Do not dedup on deliveryId — that’s unique per attempt and changes on retry.
  • Order on (entity, sequence). Deliveries can arrive out of order. Use sequence to order events for the same entity:
A robust consumer keys on eventId, drops duplicates, and never lets a lower sequence overwrite committed state for the same entity.

Securing your endpoint

v1 does not sign deliveries with an HMAC signature. Authenticate callbacks using the custom headers on your subscription. HMAC request signing is on the roadmap as an opt-in enhancement in a future apiVersion.
  • 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 orgId is one you expect and eventType is 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 synthetic webhook.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:
Return any 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

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.
Delivery is at-least-once. Dedup on eventId and design writes so re-processing the same event is a no-op.
Never assume declared arrives before resolved. Order on (emergencyId, sequence) / (deviceId, sequence) and ignore stale, lower-sequence updates.
New event types and new data fields can appear within your apiVersion. Switch on known eventTypes and ignore the rest instead of erroring.
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.
Debugging a missed or malformed delivery? Reach out to your Rescue contact with the eventId, deliveryId, and subscriptionId — that triple lets us trace exactly what we sent and when.