On this page

Use the following FHIR extensions to customize the Subscription behavior. The behavior is non-standard, and will not necessarily work in other FHIR systems.

## Adding Extensions

Here is an example FHIR Subscription Object:

```json
{
  "resourceType": "Subscription",
  "reason": "test",
  "status": "active",
  "criteria": "Patient",
  "channel": {
    "type": "rest-hook",
    "endpoint": "https://example.com/webhook"
  }
}
```

An subscription extension contains an array of objects that have `url` and `value*` in them. To add an extension, use one of medplum's url below that contains the value to be passed.

The extension will look like this:

```json
{
  "extension": [
    {
      "url": "https://medplum.com/fhir/StructureDefinition/subscription-max-attempts",
      "valueInteger": 3
    }
  ]
}
```

And your final Subscription object will be:

```json
{
  "resourceType": "Subscription",
  "reason": "test",
  "status": "active",
  "criteria": "Patient",
  "channel": {
    "type": "rest-hook",
    "endpoint": "https://example.com/webhook"
  },
  "extension": [
    {
      "url": "https://medplum.com/fhir/StructureDefinition/subscription-max-attempts",
      "valueInteger": 3
    }
  ]
}
```

Below are explanations of the different extensions Medplum Provides

## Interactions

Note

By default, FHIR Subscriptions will execute on all "create", "update", and "delete" operations. To restrict a Subscription to a subset of these interactions, use one or more `subscription-supported-interaction` extensions as described below.

You can use extensions as follows for more fine-grained control over when Subscriptions execute. To confirm if your Subscriptions are executing, navigate to `https://app.medplum.com/Subscription/<id>/event` to view related [AuditEvents](/content/docs/api/fhir/resources/auditevent/index.html). Note that if you configure the subscription to use `log`-only destination for AuditEvents (see [AuditEvent Destination](/content/docs/subscriptions/subscription-extensions#auditevent-destination/index.html)), these events will not appear in the UI.

A Subscription may declare **multiple** `subscription-supported-interaction` extensions. When one or more are present, the Subscription will only execute for the listed interactions. For example, adding one extension with `valueCode` of `create` and another with `valueCode` of `update` will fire on "create" and "update" but **not** "delete". When no `subscription-supported-interaction` extension is present, the Subscription fires on all interactions ("create", "update", and "delete").

### Subscriptions for "create"-only or "update"-only events

To restrict the FHIR Subscription to only execute on "create", use the `https://medplum.com/fhir/StructureDefinition/subscription-supported-interaction` extension with `valueCode` of `create`:

```json
{
  "resourceType": "Subscription",
  "reason": "test",
  "status": "active",
  "criteria": "Patient",
  "channel": {
    "type": "rest-hook",
    "endpoint": "https://example.com/webhook"
  },
  "extension": [
    {
      "url": "https://medplum.com/fhir/StructureDefinition/subscription-supported-interaction",
      "valueCode": "create"
    }
  ]
}
```

You can also restrict the FHIR Subscription to only execute on "update", using the `https://medplum.com/fhir/StructureDefinition/subscription-supported-interaction` extension with `valueCode` of `update`:

```json
{
  "resourceType": "Subscription",
  "reason": "test",
  "status": "active",
  "criteria": "Patient",
  "channel": {
    "type": "rest-hook",
    "endpoint": "https://example.com/webhook"
  },
  "extension": [
    {
      "url": "https://medplum.com/fhir/StructureDefinition/subscription-supported-interaction",
      "valueCode": "update"
    }
  ]
}
```

To listen for more than one interaction while excluding the others (for example, "create" and "update" but not "delete"), include a separate `subscription-supported-interaction` extension for each interaction you want:

```json
{
  "resourceType": "Subscription",
  "reason": "test",
  "status": "active",
  "criteria": "Patient",
  "channel": {
    "type": "rest-hook",
    "endpoint": "https://example.com/webhook"
  },
  "extension": [
    {
      "url": "https://medplum.com/fhir/StructureDefinition/subscription-supported-interaction",
      "valueCode": "create"
    },
    {
      "url": "https://medplum.com/fhir/StructureDefinition/subscription-supported-interaction",
      "valueCode": "update"
    }
  ]
}
```

### Subscriptions for "delete" events

Use the `https://medplum.com/fhir/StructureDefinition/subscription-supported-interaction` extension with `valueCode` of `delete`. For example:

```json
{
  "resourceType": "Subscription",
  "reason": "test",
  "status": "active",
  "criteria": "Patient",
  "channel": {
    "type": "rest-hook",
    "endpoint": "https://example.com/webhook"
  },
  "extension": [
    {
      "url": "https://medplum.com/fhir/StructureDefinition/subscription-supported-interaction",
      "valueCode": "delete"
    }
  ]
}
```

The response for a deleted resource will contain:

```json
{
  "method": "POST",
  "body": "{}",
  "headers": {
    "Content-Type": "application/fhir+json",
    "X-Medplum-Deleted-Resource": "${resource.resourceType}/${resource.id}"
  }
}
```

**_Few things to note:_**

`X-Medplum-Deleted-Resource`: Will contain the resource type and resource id that was deleted.

`body`: Will be an empty object in the response `{}`

## Signatures

When a consumer receives a webhook request, you may want to verify that the request came from the expected sender.

Webhooks can optionally use a FHIR extension to enable an HMAC signature. To enable HMAC signatures, use the extension `https://www.medplum.com/fhir/StructureDefinition/subscription-secret` and `valueString` of a cryptographically secure secret.

```json
{
  "resourceType": "Subscription",
  "reason": "test",
  "status": "active",
  "criteria": "DiagnosticReport?status=completed",
  "channel": {
    "type": "rest-hook",
    "endpoint": "https://example.com/webhook"
  },
  "extension": [
    {
      "url": "https://www.medplum.com/fhir/StructureDefinition/subscription-secret",
      "valueString": "abc"
    }
  ]
}
```

The `valueString` will be used to generate a signature. The signature is the payload encoded using SHA-256 (otherwise known as an HMAC).

## Retry Policy

If your subscription failed or threw an error, you can configure it to attempt to execute the operation multiple times.

To add an attempt number, use the `https://medplum.com/fhir/StructureDefinition/subscription-max-attempts` extension with the valueInteger set to a number between 1-18.

The default number of attempts is 4.

Note

Subscriptions with Bot endpoints will only execute once and will not retry on failure. The `subscription-max-attempts` extension only applies to rest-hook subscriptions with external HTTP endpoints.

```json
{
  "resourceType": "Subscription",
  "reason": "test",
  "status": "active",
  "criteria": "DiagnosticReport?status=completed",
  "channel": {
    "type": "rest-hook",
    "endpoint": "https://example.com/webhook"
  },
  "extension": [
    {
      "url": "https://medplum.com/fhir/StructureDefinition/subscription-max-attempts",
      "valueInteger": 3
    }
  ]
}
```

### Retry timing and backoff

Retries are not immediate. Medplum spaces them out using **exponential backoff with jitter**, which is important to understand when planning for downtime in the destination service that receives the webhook.

- **Base delay:** the first retry is delayed ~20 seconds after the initial failure.
- **Exponential growth:** each subsequent delay doubles (20s → 40s → 80s → 160s → …).
- **Maximum delay:** the delay between attempts is capped at **8 hours**.
- **Jitter:** a random factor of ±10% is applied to each delay to avoid thundering-herd retries, so actual times may vary slightly from the values below.

### Custom Status Codes

HTTP status codes can be customized to determine the success of the subscription operation.

To add custom codes, use the `https://medplum.com/fhir/StructureDefinition/subscription-success-codes` extension with the valueString having a comma separated list of HTTP status codes for success (i.e., "200,201"). We also allow ranges (i.e., "200-399,404")

```json
{
  "resourceType": "Subscription",
  "reason": "test",
  "status": "active",
  "criteria": "DiagnosticReport?status=completed",
  "channel": {
    "type": "rest-hook",
    "endpoint": "https://example.com/webhook"
  },
  "extension": [
    {
      "url": "https://medplum.com/fhir/StructureDefinition/subscription-success-codes",
      "valueString": "200-399,404"
    }
  ]
}
```

## AuditEvent Destination

Rest-hook subscriptions only

The `subscription-audit-event-destination` extension applies to **rest-hook** (`channel.type = "rest-hook"`) subscriptions. For **bot-channel** subscriptions, audit event behavior is controlled by `Bot.auditEventDestination` on the Bot resource.

### Log-only destination

To send `AuditEvent` resources only to logs (not the database):

```json
{
  "resourceType": "Subscription",
  "reason": "test",
  "status": "active",
  "criteria": "Patient",
  "channel": {
    "type": "rest-hook",
    "endpoint": "https://example.com/webhook"
  },
  "extension": [
    {
      "url": "https://medplum.com/fhir/StructureDefinition/subscription-audit-event-destination",
      "valueCode": "log"
    }
  ]
}
```

### Expression based criteria

Medplum offers an extension (`fhir-path-criteria-expression`) for triggering subscriptions based on more complex conditional logic using a [FHIRPath expression](http://hl7.org/fhirpath/N1/). This expression takes in two variables:
- `%previous`: The state of the resource _before_ the triggering event
- `%current`: The state of the resource _after_ the triggering event.

Here is an example `Subscription` resource with a `fhir-path-criteria-expression` expression that fires when a [`Task`](/content/docs/api/fhir/resources/task/index.html) changes its status:

```json
{
  "resourceType": "Subscription",
  "reason": "Task Status Change",
  "status": "active",
  "channel": {
    "type": "rest-hook",
    "endpoint": "https://example.com/webhook"
  },
  "criteria": "Task",
  "extension": [
    {
      "url": "https://medplum.com/fhir/StructureDefinition/fhir-path-criteria-expression",
      "valueString": "%previous.status != %current.status"
    }
  ]
}
```

- [Adding Extensions](/content/docs/subscriptions/subscription-extensions#adding-extensions/index.html)
- [Interactions](/content/docs/subscriptions/subscription-extensions#interactions/index.html)
