Handling notifications

Whenever resources are created or updated to match the criteria of an active subscription, the server attempts to POST a notification to the endpoint URL specified in the subscription.

An example notification payload looks like this:

{
    "resourceType": "Bundle",
    "type": "subscription-notification",
    "entry": [
        {
            "resource": {
                "resourceType": "SubscriptionStatus",
                "status": "active",
                "type": "event-notification",
                "eventsSinceSubscriptionStart": 113,
                "notificationEvent": [
                    {
                        "eventNumber": 112,
                        "focus": {
                            "reference": "Observation/ab89f39d"
                        }
                    },
                    {
                        "eventNumber": 113,
                        "focus": {
                            "reference": "Observation/ac8a887e"
                        }
                    }
                ],
                "subscription": {
                    "reference": "Subscription/42"
                }
            }
        }
    ]
}

The notification endpoint needs to acknowledge the receipt of the handshake by returning an HTTP 200 OK status. After this, the subscriber can fetch the referenced resources by issuing a single request of the following form:

curl -sS -X GET --json @updated-subscription.json "https://${server}/fhir/r5/api/Observation?_id=123f1a05-333b-4b62-9c8a-07aa506ccc15,08ab766e-8169-4065-883a-803b1dbd7a97" \
  -H "client_id: ${client_id}" \
  -H "client_secret: ${client_secret}" \
  -H "org_id: ${org_id}" \
  -H "certificate: ${certificate}" | jq

Example response with one successful and one failed result (as indicated by entry.search.mode):

{
  "resourceType": "Bundle",
  "type": "searchset",
  "entry": [
    {
      "resource": {
        "resourceType": "Observation",
        "id": "123f1a05-333b-4b62-9c8a-07aa506ccc15",
        "meta": {"versionId": "1720619599332", "lastUpdated": "2024-07-10T13:53:19.332+00:00", "profile": ["http://roche.com/fhir/iop/StructureDefinition/BG_Observation"]},
        "status": "final",
        "code": {"coding": [{"system": "http://loinc.org", "code": "32016-8", "display": "Glucose [Mass/volume] in Capillary blood"}]},
        "subject": {"reference": "Patient/wnvhhuat6vT7s0uQ33Jv0AiOLQheBv1"},
        "effectiveTiming": {"event": ["2024-07-10T13:53:17+00:00"]},
        "valueQuantity": {"value": 100, "unit": "mg/dL", "system": "http://unitsofmeasure.org", "code": "mg/dL"}
      },
      "search": {"mode": "match"}
    },
    {
      "resource": {
        "resourceType": "OperationOutcome",
        "issue": [
          {"severity": "error", "code": "forbidden", "diagnostics": "Data sharing is not allowed"},
          {"severity": "error", "code": "processing", "details": {"text": "Problem encountered with requested resource Observation/08ab766e-8169-4065-883a-803b1dbd7a97"}}
        ]
      },
      "search": {"mode": "outcome"}
    }
  ]
}

A few key points are worth mentioning here:

  • The notification endpoint should first save the notification content and acknowledge its receipt and only then should it fetch resources, otherwise it could exceed the maximum timeout. (The default timeout is 10 seconds but can be overridden using the timeout field of the Subscription resource. The maximum allowed value in 20 seconds.)
  • If the notification endpoint does not return an HTTP 200 OK status in time (i.e., it returns something else or it doesn't return at all), the server will move the subscription to an error state (discussed in a later section).
  • Subscribers are encouraged to use the presented way of fetching multiple resources in a single request, instead of fetching them one by one. This significantly reduces the overhead of these operations. Up to 100 ID-s are allowed per request but the 2048 characters total length limit of URL-s also need to be obeyed at the same time.
  • Notifications may arrive out of order or multiple times. This is not an error and therefore it should be handled by the subscriber gracefully.
  • The same event (with identical content) may get delivered in multiple notification bundles. This is not an error and therefore it should be handled by the subscriber gracefully.
  • Multiple events in a single notification bundle may refer to the same resource. In such a case, it is enough to fetch the resource once (but if after fetching the resource, a new event arrives that references it, then it needs be fetched again, because it may have been updated since the last fetch).

Sequence diagram

The notification handling workflow can be represented in a sequence diagram as follows: