Webhooks

How Medblocks pushes events to your server: endpoints, event types, signatures, retries, and auto-disable.

Webhooks let Medblocks notify your backend the moment something happens in Connect. A PatientFlow finishes, a refresh token stops working, a background pull settles. Your server registers an HTTPS endpoint and Medblocks delivers signed JSON payloads to it.

This page covers the model. For working receiver code, see the Webhooks section.

Endpoint

An endpoint is the URL on your server that receives deliveries. It is owned by an organization, has a public id (wh_*), and stores:

FieldPurpose
urlYour HTTPS endpoint. http://localhost is allowed only for local dev.
eventsEvent-type filter. Either ["*"] (everything) or an explicit list of event types.
statusactive accepts deliveries; disabled skips them. Auto-flipped after the retry worker exhausts attempts.
descriptionOptional dashboard label.
metadataUp to 50 arbitrary keys you control, echoed back on reads.
api_versionAPI version pinned at registration. Immutable. Every event fired by this endpoint carries the same version.

Event

An event is one delivery attempt for one fact. It has its own public id (evt_*) and travels in this envelope:

{
  "id": "evt_01J9YR9N3X4VZ6P2K5RH7M3LMP",
  "object": "event",
  "type": "patient_flow.completed",
  "api_version": "2026-04-25",
  "created_at": "2026-04-25T14:35:00.000Z",
  "data": { "object": { "id": "pf_...", "resource_type": "patient_flow", "..." : "..." } }
}

event.type is the discriminator. event.data.object is shaped by type. The four event types are:

TypeFires when
patient_flow.completedA patient finishes the hosted flow (success or failure).
connection.token_refresh_failedA previously-active connection lost its refresh token and the patient needs to reconnect.
records.sync.completedA background pull finished and new records are available.
records.sync.failedA background pull errored and will not retry without intervention.

Signature

Every delivery includes a Medblocks-Signature header of the form:

t=1714060800,v1=<hex>

The HMAC-SHA256 v1 digest is computed over ${t}.${rawBody} with your endpoint’s signing secret. The secret is returned once when you create or rotate the endpoint. Store it server-side.

Two failure modes the signature protects against:

  • Replay. The timestamp t must be within a tolerance window (default 5 minutes). Reject older deliveries.
  • Tampering. The HMAC catches any body or header modification in transit.

See Webhook Signatures for the verification implementation and the raw-body trap that frameworks fall into.

Retries

Medblocks retries delivery with exponential backoff if your receiver returns a non-2xx response or times out. Each attempt updates event.attempts, event.next_attempt_at, event.last_status_code, and event.last_response_body (truncated to 4 KB).

After the retry worker exhausts attempts on one endpoint, that endpoint is auto-flipped to disabled — no event is emitted for this transition. Detect it by polling GET /webhooks/{id} (or your dashboard). Fix the receiver, then re-enable via PATCH /webhooks/{id} with status: "active".

Manual Redelivery

POST /events/{id}/redeliver re-enqueues the same event.id for another attempt. Useful after fixing a bug in your receiver. Receivers must be idempotent: the same event.id is delivered again, so dedupe by id.

Redelivery is rate-limited to one call per minute per event.

API Version Pinning

api_version on the endpoint freezes the payload shape. When Medblocks ships a breaking change to an event payload, existing endpoints keep receiving the old shape until you opt in by creating (or updating) the endpoint at a newer version. Pin the version your receiver was written against.