Skip to content

Webhooks Overview

Spry Webhooks deliver real-time notifications to your endpoint when patient, appointment, and case events happen in the Spry EMR. Each webhook is an HTTP POST carrying a JSON payload signed with HMAC-SHA256, and failed deliveries are retried automatically.

This reference covers:

Payload Format

This documentation covers the 2026-06-11 payload version (the current, minimized format). Each webhook body is wrapped in a common envelope; the event-specific data lives under data. The minimized format carries only the resource id(s), organisation_id, and a little non-PHI status — you fetch the full record from the Spry API by id.

{
  "event_id": "evt_8f3a2b9c-1234-4567-89ab-cdef01234567",
  "event_type": "appointment.updated",
  "api_version": "2026-06-11",
  "timestamp": 1776246130,
  "data": {
    "organisation_id": 74,
    "appointment_id": 113191,
    "patient_id": 45675,
    "spry_case_id": "SPRY_CASE_69d778fa05e30511a1a2b282",
    "clinic_id": 44,
    "status": "PATIENT_CHECKIN"
  }
}

Envelope Fields

Field Type Description
event_id string Unique webhook delivery ID, prefixed evt_. Use this as your idempotency key.
event_type string One of the values in Event Types.
api_version string The payload format version this body conforms to (2026-06-11). Pinned per subscription.
timestamp integer Epoch seconds — when Spry dispatched the webhook.
data object Identifiers + status for the affected resource. organisation_id is always present; the other fields depend on the event family. No PHI is included — fetch the full record from the Spry API by id.

HTTP Headers

Every webhook POST includes:

Header Value Purpose
Content-Type application/json
X-Sprypt-Signature t=<epoch>,v1=<hmac> Signature — see Signature Verification
X-Event-Type e.g. appointment.updated Mirrors event_type in body
X-Event-Id e.g. evt_8f3a2b9c-... Mirrors event_id in body
X-Delivery-Id UUID of this delivery attempt Quote this when reporting delivery issues
X-Sprypt-Api-Version e.g. 2026-06-11 The api_version that produced this payload
User-Agent SpryWebhookService/2.0

API Versioning

Every webhook payload carries an api_version that pins its format. A subscription is locked to one version at creation time, so a future breaking change to the payload shape won't break you — you keep receiving the format you subscribed to until you explicitly upgrade.

  • Choosing a version: pass api_version when you create a subscription. Omit it to get the latest (2026-06-11). An unknown version is rejected with 400 INVALID_API_VERSION.
  • Pinning: the version is fixed for the life of the subscription. New versions never silently change an existing subscription's payloads.
  • Upgrading: PATCH /api/v2/subscriptions/:id with a new api_version to move a subscription forward.

Acknowledging Webhooks

Your endpoint must:

  1. Accept POST with a JSON body.
  2. Return a 2xx status code (typically 200 OK).
  3. Respond within 10 seconds.
  4. Use event_id as an idempotency key — your endpoint should be safe to call twice with the same event_id.

Any other status code, a network error, or a timeout is treated as a failure and triggers the retry schedule below.

Tip: Acknowledge first, process asynchronously. Read the payload into a queue and return 200 immediately; do the actual work in a background worker. Webhooks that take more than 10 seconds to process will retry unnecessarily.

Retry Behaviour

Failed deliveries are retried on a 5-attempt backoff schedule.

Attempt Delay after previous failure Cumulative time
1st (initial) 0
2nd 15 seconds 15 s
3rd 1 minute ~1 min 15 s
4th 10 minutes ~11 min
5th 1 hour ~1 h 11 min
Final 6 hours ~7 h

If all retries fail, the delivery is considered failed and is no longer attempted.