> For the complete documentation index, see [llms.txt](https://docs.mdintegrations.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.mdintegrations.com/partner/troubleshooting/technical-concepts/webhook-setup-and-signature-verification.md).

# Webhook Setup & Signature Verification

Webhooks are how MDI pushes real-time updates to your system — an Encounter changing status, a message being sent, a pharmacy order updating — without you having to poll the API for changes. This page covers how to configure an endpoint and how to verify that the payloads you receive genuinely came from MDI.

## How delivery works

You configure a single HTTPS endpoint per environment in the Partner Portal. When a triggering event occurs on MDI's side, that event is placed on a delivery queue and sent to your endpoint as an HTTP POST.

{% hint style="info" %}
Delivery is asynchronous. A webhook is queued and delivered independently of the API call or action that triggered it — never assume a webhook has already fired (or fired yet) just because a related API call returned successfully. Build your integration to react to the webhook arriving, not to the timing of the action that caused it.
{% endhint %}

Sandbox and Live each have their own webhook endpoint configuration and their own signing secret. An endpoint registered for Sandbox never receives Live events, and vice versa — see Sandbox vs. Live Environments for the broader environment split.

## Configuring your endpoint

{% stepper %}
{% step %}
Log in to the Partner Portal as an admin user.
{% endstep %}

{% step %}
Go to **Integration** → **Webhooks**.
{% endstep %}

{% step %}
Click **Add new**.
{% endstep %}

{% step %}
Select the environment you're subscribing for — **Sandbox** or **Live**. These are separate subscriptions; each has its own URL and security configuration.
{% endstep %}

{% step %}
Enter the HTTPS URL you want events delivered to. MDI will not deliver to a non-HTTPS URL.
{% endstep %}

{% step %}
Configure webhook security (see below), then save.
{% endstep %}
{% endstepper %}

Once your endpoint is live, it should respond quickly with a 2xx status as soon as it has received the payload, then handle any heavier processing afterward, asynchronously, on your own side. See Retry Policy & Idempotency for what happens when it doesn't.

## Two layers of webhook security

When you configure a webhook, MDI gives you two separate security mechanisms. It's worth keeping them straight, since they check different things and neither is a substitute for the other:

| Mechanism         | What it is                                                                           | What it proves                                                                             |
| ----------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
| **Secret**        | Used to generate a unique HMAC-SHA256 hash sent in the request's `Signature` header. | Data integrity — that the payload wasn't tampered with in transit.                         |
| **Authorization** | A separate, static header value you set, sent as-is on every request.                | Origin — a simpler check, like a shared password, that the request actually came from MDI. |

Think of the **Authorization** header as an extra layer on top of signature verification, not a replacement for it — validate both on every request. The Authorization check is a cheap first filter you can reject on quickly; the Secret-based signature is what actually confirms the payload's contents weren't altered along the way.

## Verifying the signature

Every webhook payload is signed using **HMAC-SHA256** with your environment's webhook secret. Before trusting the contents of any payload, verify it using the steps below:

{% stepper %}
{% step %}
Retrieve your webhook secret for the relevant environment from the Partner Portal.
{% endstep %}

{% step %}
Recompute the HMAC-SHA256 signature over the raw request body using that secret.
{% endstep %}

{% step %}
Compare your computed signature against the value in the request's `Signature` header.
{% endstep %}

{% step %}
Separately, confirm the request's `Authorization` header matches the static value you configured.
{% endstep %}

{% step %}
Only process the payload if both checks pass. Reject (and don't act on) any request where either doesn't match.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
Verify against the raw, unparsed request body — not a re-serialized version of it. Parsing the payload into an object and re-encoding it before hashing can change whitespace or key ordering and produce a signature mismatch even for a legitimate MDI request.
{% endhint %}

Because Sandbox and Live use different secrets and Authorization values, make sure your verification logic reads whichever values match the environment the request is actually coming from — not a single hardcoded value shared between the two.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.mdintegrations.com/partner/troubleshooting/technical-concepts/webhook-setup-and-signature-verification.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
