Webhook Delivery & Security

When a change, such as a new patient document, a new lab result, or a completed asynchronous request, matches one of your subscriptions, Health Gorilla sends a notification to your registered endpoint. What's sent depends on the subscription's payload type. You can use the headers on each notification to detect duplicate deliveries and, if you set up a signing secret or OAuth 2.0, to confirm that it came from Health Gorilla.

Endpoint Requirements

Your endpoint must use HTTPS, and its host must be a hostname, not an IP address. A subscription with any other endpoint is rejected when you create it or change its endpoint.

Any headers you list in the subscription's channel.header, such as a shared key that your endpoint checks, are added to every notification.

Payload Types

Where a notification is sent and what it contains depend on the channel.payload you set on the subscription.

channel.payloadSent toContains
application/fhir+jsonYour endpoint with the resource type added, such as https://yourapp.com/webhooks/DocumentReferenceThe full FHIR resource, with Content-Type: application/fhir+json
application/hg-event+jsonYour endpoint as registeredA small JSON object with the resource type and ID, plus "deleted": true when the resource was deleted, with Content-Type: application/json
Not setYour endpoint as registeredNothing. The empty request only signals a change, so retrieve the change with a _lastUpdated search.

Note: For application/fhir+json subscriptions with API version January 2023 or earlier, a notification about an updated resource is sent as a PUT to your endpoint with the resource type and ID added, for example /DocumentReference/12345.

Example: FHIR Payload Notification

The subscription's registered endpoint is https://yourapp.com/webhooks, and it has a signing secret.

POST /webhooks/DocumentReference HTTP/1.1
Host: yourapp.com
Content-Type: application/fhir+json
Date: Tue, 13 Oct 2026 18:27:00 GMT
X-Hg-EventId: 6528f1c2e4b0a1d2c3e4f5a6
X-Hg-EventCreated: Tue, 13 Oct 2026 18:26:58 GMT
Digest: sha-512=<hex SHA-512 of the body>
X-Hg-Signature: sha512=<hex HMAC-SHA512>

{
  "resourceType": "DocumentReference",
  "id": "12345",
  "status": "current",
  "type": {
    "coding": [
      {
        "system": "http://loinc.org",
        "code": "34133-9",
        "display": "Summarization of episode note"
      }
    ]
  },
  "subject": {
    "reference": "Patient/abc-123"
  },
  "date": "2024-11-01T18:27:00Z"
}

Example: Event Payload Notification

The subscription uses the same endpoint with the application/hg-event+json payload, so the notification goes to the endpoint as registered.

POST /webhooks HTTP/1.1
Host: yourapp.com
Content-Type: application/json
Date: Tue, 13 Oct 2026 18:27:00 GMT
X-Hg-EventId: 6528f1c2e4b0a1d2c3e4f5a6
X-Hg-EventCreated: Tue, 13 Oct 2026 18:26:58 GMT
Digest: sha-512=<hex SHA-512 of the body>

{
  "resource": "DocumentReference",
  "id": "DocumentReference/12345"
}

Example: Notification Without a Payload

The subscription uses the same endpoint and doesn't set channel.payload, so the request has headers and no body.

POST /webhooks HTTP/1.1
Host: yourapp.com
Date: Tue, 13 Oct 2026 18:27:00 GMT
X-Hg-EventId: 6528f1c2e4b0a1d2c3e4f5a6
X-Hg-EventCreated: Tue, 13 Oct 2026 18:26:58 GMT
Digest: sha-512=<hex SHA-512 of an empty body>

Headers

Every notification carries Date, X-Hg-EventId, X-Hg-EventCreated, and Digest. The others depend on how the subscription is set up.

HeaderWhen sentValue
DateAlwaysWhen the notification was sent, as an HTTP date in GMT
X-Hg-EventIdAlwaysThe ID of the event that produced the notification. One event can produce several notifications, one per resource, with the same ID, and a retry carries the same ID.
X-Hg-EventCreatedAlwaysWhen the event was created, as an HTTP date in GMT
DigestAlwayssha-512= followed by the lowercase hex SHA-512 hash of the body. It confirms the body wasn't altered, not who sent it.
X-Hg-SignatureThe subscription has a signing secretsha512= followed by the lowercase hex HMAC-SHA512 signature
AuthorizationThe subscription uses OAuth 2.0Bearer and an access token from your authorization server
X-Hg-DeletedThe resource was deletedtrue
Your channel.header valuesYou listed them on the subscriptionAs you defined them

Verifying Notifications

You can confirm that notifications come from Health Gorilla with a signing secret or with OAuth 2.0. If a subscription has both, OAuth 2.0 is used, and notifications aren't signed. You can also add a shared key in channel.header, with either method or on its own.

Signing Secret

To have notifications signed, add a signing secret to the subscription's channel. The secret must be a Base64 string that decodes to at least 64 bytes.

Example: Signing Secret Extension

"channel": {
  "type": "rest-hook",
  "endpoint": "https://yourapp.com/webhooks",
  "payload": "application/fhir+json",
  "extension": [
    {
      "url": "https://www.healthgorilla.com/fhir/StructureDefinition/subscription-channelSecret",
      "extension": [
        {
          "url": "value",
          "valueString": "<Base64 secret>"
        }
      ]
    }
  ]
}

To verify a signed notification, confirm that the body matches the Digest header and that the X-Hg-Signature header matches a signature you compute with your secret.

  1. Hash the raw request body with SHA-512, write the result as lowercase hex, and add sha-512= to the front. The result must equal the Digest header.
  2. Join the values of the Date, X-Hg-EventId, and Digest headers, in that order, with a newline between each.
  3. Compute an HMAC-SHA512 of that string, using your secret as the key exactly as you entered it on the subscription, without Base64-decoding it first. Write the result as lowercase hex, and add sha512= to the front.
  4. Confirm that the result equals the X-Hg-Signature header, using a constant-time comparison.

Note: The two prefixes differ. The Digest header uses sha-512=, with a hyphen, and the signature uses sha512=, without one.

Example: Signature Test Values

You can test your implementation with these values. The secret is 64 bytes of sample data, and the body is the event payload example without spaces.

Secret:         AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw==
Date:           Tue, 13 Oct 2026 18:27:00 GMT
X-Hg-EventId:   6528f1c2e4b0a1d2c3e4f5a6
Body:           {"resource":"DocumentReference","id":"DocumentReference/12345"}
Digest:         sha-512=d37bb920f99e89daf1ff8fbc6fa8228e2ca9a8374044daa3f1cc7d52ee20ce1ab311c59fdae94ffa70396fe95c0f0cba0462348eda3af918e3eca6422349f68f
X-Hg-Signature: sha512=4cc3ba9be0c02b46863c81b72c3382d3e8c1d9c6e763aa854c8a26268b0ba32072a8212c562c19955326df6042634d8395d4a6926aa8069020dfc970136b338e

OAuth 2.0

With OAuth 2.0, Health Gorilla requests an access token from your authorization server using the client credentials flow, and sends it in the Authorization header. The token is reused until it expires. If your endpoint responds with 401 or 403, the token is discarded, and a new one is requested on the next attempt. The configuration is described on Subscribing to Events.

Responding to Notifications

Respond with 200 OK to confirm receipt, which counts as success for every payload type. Other codes depend on the payload type:

  • application/fhir+json: Any 2xx response counts as success, unless its body is an OperationOutcome with an error or fatal issue.
  • application/hg-event+json: Only 200 and 201 count as success.
  • No payload: Only 200 counts as success.

Respond as soon as you've received the notification, and do any further processing afterward.

Retries and Failures

A delivery fails when your endpoint returns a failure status, times out, or can't be reached. Health Gorilla retries a failed delivery every 15 minutes, up to five times, and drops the notification after the last retry. After repeated failures, the subscription can be disabled. The conditions are listed on Subscribing to Events.

Because retries come 15 minutes apart, a retried notification can arrive after a newer one for the same resource. Compare meta.lastUpdated before you overwrite stored data. To catch up after missed notifications, search with _lastUpdated, as described on Polling.

Duplicate Deliveries

Design your endpoint to be idempotent, so processing the same notification twice has no extra effect. A notification can arrive more than once, for example when your endpoint processed it but the response timed out. To detect a duplicate delivery, compare X-Hg-EventId together with the resource ID. One event can produce several notifications with the same X-Hg-EventId, one per resource. For FHIR payloads, you can also compare the resource's id and meta.lastUpdated.