> ## Documentation Index
> Fetch the complete documentation index at: https://docs.develophealth.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Provider outreach webhooks

> Receive the content and lifecycle of communications sent to providers.

<Note>
  **Beta:** Contact support to enable provider outreach webhooks. Breaking
  changes may occur during the beta period.
</Note>

Provider outreach webhooks are only emitted for prior authorization requests.
Provider outreach is activated when Develop Health contacts the prescribing
provider to request information or action, or to communicate an outcome.

The `prior_authorization.provider_outreach_change` event is emitted when a
provider outreach attempt is created or changes state, or when the outreach
sequence reaches a terminal state. Each event is a complete snapshot of one
communication attempt, including its current state and, after the communication
is rendered, the exact message content and files sent to the provider.

## Webhook body

```jsonc theme={null}
{
  "event_id": "wh_evt_pQrStUv",
  "occurred_at": "2026-07-29T18:12:04Z",
  "title": "Prior Authorization Provider Outreach Updated",
  "description": "A provider outreach attempt or sequence changed state.",
  "event_type": "prior_authorization.provider_outreach_change",
  "data": {
    "id": "prov_outreach_aBcDeFg",
    "object": "provider_outreach",
    "outreach_sequence_id": "prov_outreach_seq_rStUvWx",
    "prior_authorization_id": "pa_req_hIjKlMn",
    "attempt_number": 1,
    "purpose": "document_request",
    "communication_method": "fax",
    "status": "sent",
    "sequence_status": "active",
    "provider": {
      "first_name": "Avery",
      "last_name": "Chen",
      "npi": "1234567890"
    },
    "transmission": {
      "subject": "Prior authorization information requested",
      "body": "Please review the attached request and respond using the instructions provided.",
      "body_content_type": "text/plain",
      "attachments": [
        {
          "id": "provider_outreach_attachment_xYz123",
          "file_name": "provider_outreach_aBcDeFg.pdf",
          "content_type": "application/pdf",
          "sha256": "ddb53b2d5bb9f21df813d4144f65b13f8d4f72d77c47b37701ba5d9344e335cf",
          "url": "https://files.develophealth.ai/signed/example"
        }
      ]
    },
    "sent_at": "2026-07-29T18:12:04Z",
    "delivered_at": null,
    "opened_at": null,
    "processing_started_at": null,
    "completed_at": null,
    "outreach_window_ends_at": "2026-08-04T18:12:01Z",
    "expires_at": "2026-08-05T18:12:04Z",
    "created_at": "2026-07-29T18:12:01Z",
    "updated_at": "2026-07-29T18:12:04Z"
  }
}
```

### Envelope fields

| Field         | Type   | Description                                                                     |
| ------------- | ------ | ------------------------------------------------------------------------------- |
| `event_id`    | string | Stable ID for the event. Use it to deduplicate delivery retries.                |
| `occurred_at` | string | When the attempt or sequence state changed, not when the webhook was delivered. |
| `title`       | string | Human-readable event title. Do not use this field for program logic.            |
| `description` | string | Human-readable event description. Do not use this field for program logic.      |
| `event_type`  | string | Always `prior_authorization.provider_outreach_change`.                          |
| `data`        | object | Complete snapshot of the provider outreach.                                     |

### Data fields

| Field                     | Type           | Description                                                                                                              |
| ------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `id`                      | string         | Stable ID for this channel attempt. A retry or parallel send through another channel has a different ID.                 |
| `object`                  | string         | Always `provider_outreach`.                                                                                              |
| `outreach_sequence_id`    | string         | Stable ID shared by all channel attempts and retries for the same provider outreach sequence.                            |
| `prior_authorization_id`  | string         | ID of the related prior authorization.                                                                                   |
| `attempt_number`          | integer        | One-based retry round within the sequence. Attempts sent through multiple channels in parallel can have the same number. |
| `purpose`                 | string         | Why the provider was contacted: `document_request` or `outcome_notification`.                                            |
| `communication_method`    | string         | Delivery channel: `email`, `sms`, `fax`, or `dsm`.                                                                       |
| `status`                  | string         | Current state of this channel attempt. See [Attempt states](#attempt-states).                                            |
| `sequence_status`         | string         | Current state across all attempts in the outreach sequence. See [Sequence states](#sequence-states).                     |
| `provider`                | object         | Provider identity associated with the outreach.                                                                          |
| `provider.first_name`     | string or null | Provider's first name.                                                                                                   |
| `provider.last_name`      | string or null | Provider's last name.                                                                                                    |
| `provider.npi`            | string or null | Provider's National Provider Identifier.                                                                                 |
| `transmission`            | object or null | Rendered content sent to the provider. This may be `null` while the outreach is `pending` or when rendering failed.      |
| `sent_at`                 | string or null | When the communication was handed to the delivery channel.                                                               |
| `delivered_at`            | string or null | When delivery was confirmed, if the channel supports confirmation.                                                       |
| `opened_at`               | string or null | When the provider first opened the secure outreach link.                                                                 |
| `processing_started_at`   | string or null | When the provider began the requested response workflow.                                                                 |
| `completed_at`            | string or null | When the provider completed the requested action.                                                                        |
| `outreach_window_ends_at` | string or null | Configured deadline after which no new attempts will be scheduled for this sequence.                                     |
| `expires_at`              | string or null | When secure access for this channel attempt expires. This is independent of `outreach_window_ends_at`.                   |
| `created_at`              | string         | When this outreach attempt was created.                                                                                  |
| `updated_at`              | string         | When this snapshot last changed.                                                                                         |

### Transmission fields

The `transmission` object shows what was sent, not a template name or template
variables. Once an attempt reaches `sent`, the rendered transmission is
immutable for that attempt ID.

| Field                        | Type           | Description                                                                                   |
| ---------------------------- | -------------- | --------------------------------------------------------------------------------------------- |
| `subject`                    | string or null | Rendered subject or fax cover-page description. `null` for SMS.                               |
| `body`                       | string or null | Rendered message body. For a fax, the exact rendered document is provided in `attachments`.   |
| `body_content_type`          | string or null | MIME type of `body`, such as `text/plain` or `text/html`.                                     |
| `attachments`                | array          | Files delivered with the outreach. An empty array means no files were attached.               |
| `attachments[].id`           | string         | Stable ID for the transmitted file.                                                           |
| `attachments[].file_name`    | string         | Filename shown to the recipient.                                                              |
| `attachments[].content_type` | string         | MIME type of the file.                                                                        |
| `attachments[].sha256`       | string         | Lowercase SHA-256 digest of the transmitted file. Verify downloaded bytes against this value. |
| `attachments[].url`          | string         | Short-lived signed download URL for the exact transmitted file.                               |

Transmission content varies by channel:

| Channel | Transmission content                                                 |
| ------- | -------------------------------------------------------------------- |
| `email` | Rendered subject and body, plus any email attachments.               |
| `sms`   | Rendered text body; `subject` is `null` and `attachments` is empty.  |
| `fax`   | Cover-page description and the exact fax PDF in `attachments`.       |
| `dsm`   | Rendered Direct message subject and body, plus its MIME attachments. |

<Note>
  Attachment URLs expire quickly. Download required files when you receive the
  webhook instead of storing the URL. Provider outreach can contain protected
  health information and secure access credentials, so protect webhook payloads
  and downloaded files accordingly.
</Note>

## Attempts, retries, and parallel channels

Each payload describes one communication attempt through one channel. When
Direct Secure Messaging and fax are sent in parallel, for example, each has its
own `id`, `communication_method`, status, and transmission. Both attempts share
an `outreach_sequence_id` and can have the same `attempt_number`.

A retry has a new attempt `id` and an incremented `attempt_number`. The outreach
window is configurable for each workflow; do not assume a fixed number of days
or attempts. Use `outreach_window_ends_at` to determine when Develop Health will
stop scheduling new attempts.

When the sequence reaches `completed` or `failed`, Develop Health emits another
`prior_authorization.provider_outreach_change` event for its most recent
attempt. That event has a new `event_id` and the updated `sequence_status`; the
attempt's rendered transmission remains unchanged.

## Attempt states

| State        | Meaning                                                                                                                 |
| ------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `pending`    | The outreach attempt exists but has not been handed to a delivery channel. The transmission may not be rendered yet.    |
| `sent`       | The delivery channel accepted the communication. The complete rendered transmission is included.                        |
| `delivered`  | The delivery channel confirmed delivery. Not every channel reports this state.                                          |
| `opened`     | The provider opened the secure outreach link for the first time.                                                        |
| `processing` | The provider began the requested response workflow, such as uploading documents or answering PA questions.              |
| `completed`  | The provider completed the requested action.                                                                            |
| `expired`    | Secure access for this attempt expired or the attempt was cancelled before completion.                                  |
| `failed`     | This communication attempt could not be rendered, sent, or processed. Other attempts in the sequence may still proceed. |

An attempt does not necessarily pass through every state. For example, a fax
may move from `sent` directly to `completed`, because delivery and open signals
are not available for every channel. Treat `completed`, `expired`, and `failed`
as terminal for one attempt ID. A later retry or escalation is represented by a
new attempt ID.

## Sequence states

| State       | Meaning                                                                                                        |
| ----------- | -------------------------------------------------------------------------------------------------------------- |
| `active`    | At least one attempt is in progress, or more attempts may be scheduled.                                        |
| `completed` | The sequence reached its success condition, such as the provider completing the requested action.              |
| `failed`    | The configured outreach window ended or all available channels were exhausted without completing the sequence. |

Attempt and sequence states are independent. For example, a fax can be
`delivered` while its sequence eventually becomes `failed` because the provider
did not complete the requested action.

## Processing events

Webhook deliveries may be duplicated. Deduplicate delivery retries by
`event_id`, and ignore state values your integration does not recognize.

Return a 2xx response as soon as the event is durably accepted. Download any
required attachments promptly, verify each file against its `sha256` value,
then process the event asynchronously.
