diff --git a/SUMMARY.md b/SUMMARY.md
index 3fd086c..a046b7e 100644
--- a/SUMMARY.md
+++ b/SUMMARY.md
@@ -12,7 +12,6 @@
* [MPF Pipeline](run-payerbox/provider-directory-pipeline.md)
* [Maintain](run-payerbox/maintain/README.md)
* [Observability](run-payerbox/maintain/observability.md)
- * [Event Notifications](run-payerbox/maintain/event-notifications.md)
* [Upgrade](run-payerbox/maintain/upgrade.md)
* [Interop APIs](interop-apis/README.md)
* [Patient Access](interop-apis/patient-access.md)
@@ -25,6 +24,7 @@
* [Aidbox as Questionnaire storage](prior-auth/dtr/aidbox-questionnaire-package.md)
* [DTR SMART App](prior-auth/dtr/dtr-smart-app.md)
* [PAS](prior-auth/pas.md)
+ * [Event Notifications](prior-auth/event-notifications.md)
* [FHIR App Portal](fhir-app-portal/README.md)
* [Developer Portal](fhir-app-portal/developer-portal.md)
* [Admin Portal](fhir-app-portal/admin-portal.md)
diff --git a/docs/prior-auth/event-notifications.md b/docs/prior-auth/event-notifications.md
new file mode 100644
index 0000000..0bc0ec4
--- /dev/null
+++ b/docs/prior-auth/event-notifications.md
@@ -0,0 +1,160 @@
+---
+description: >-
+ Receive Prior Auth events from Payerbox using standard FHIR topic-based
+ subscriptions — define a topic, create a Subscription with a rest-hook
+ channel, and handle the notification bundle.
+---
+
+# Event Notifications
+
+Payerbox can push FHIR resource events to subscribers as they happen — for example, notifying a downstream system the moment a prior-authorization decision is recorded on a `ClaimResponse`. It is built on **FHIR R4B topic-based subscriptions** and configured entirely through standard FHIR resources.
+
+For the regulatory and workflow context of the events themselves, see [PAS](pas.md). For platform details beyond what this page covers, see [FHIR Topic-Based Subscriptions](https://www.health-samurai.io/docs/aidbox/modules/topic-based-subscriptions/fhir-topic-based-subscriptions) in the Aidbox docs.
+
+## How it works
+
+Two resources work together:
+
+| Resource | Role |
+|---|---|
+| `AidboxSubscriptionTopic` | The **topic** — which resource type, an optional FHIRPath criterion, and which interactions (create / update / delete) fire it. Models the FHIR `SubscriptionTopic` concept. |
+| `Subscription` | The **subscriber** — a standard FHIR R4B `Subscription` a client creates to receive notifications. It references the topic and carries the delivery channel (a rest-hook endpoint). |
+
+When a CRUD operation matches a topic's trigger, Aidbox delivers a notification bundle to every active `Subscription` bound to that topic. Delivery is asynchronous, so a slow or unavailable subscriber never blocks the originating FHIR write.
+
+```mermaid
+graph LR
+ W(FHIR write
create / update / delete):::blue2 --> T(AidboxSubscriptionTopic
trigger + FHIRPath):::blue2
+ T --> S(Subscription
rest-hook channel):::blue2
+ S --> E(Subscriber
HTTPS endpoint):::green2
+```
+
+### Delivery lifecycle
+
+A `Subscription` moves through a handshake before it delivers events:
+
+1. **`requested`** — the state a new `Subscription` is created in. Aidbox immediately POSTs a **handshake** notification (a bundle whose `SubscriptionStatus.type` is `handshake`) to the channel endpoint to validate it.
+2. **`active`** — the endpoint answered the handshake with an HTTP `2xx`. Only then does Aidbox begin delivering event notifications. A non-2xx leaves the subscription inactive.
+3. **`error` / `off`** — repeated delivery failures deactivate the subscription; it must be re-created or reset to resume.
+
+Each event notification is a `Bundle` containing a `SubscriptionStatus` resource (event metadata) followed by the triggering resource(s). If a heartbeat period is configured, Aidbox also sends periodic empty notifications during idle stretches so the subscriber can tell a quiet pipeline from a broken one.
+
+## Configure a notification
+
+Create the resources below with admin credentials. In production they are usually provisioned from an init-bundle — see [Provisioning at deploy time](#provisioning-at-deploy-time).
+
+{% stepper %}
+{% step %}
+
+### Define the subscription topic
+
+Declare what to notify on. `trigger.fhirPathCriteria` narrows the firing condition; omit it to fire on every interaction of the resource type. For Prior Auth, trigger on the `ClaimResponse` that carries the decision.
+
+{% code title="PUT /AidboxSubscriptionTopic/pas-claimresponse-status" %}
+```json
+{
+ "resourceType": "AidboxSubscriptionTopic",
+ "id": "pas-claimresponse-status",
+ "url": "http://prior-auth.example.org/SubscriptionTopic/pas-claimresponse-status",
+ "status": "active",
+ "description": "Notify when PAS ClaimResponses are created or updated",
+ "trigger": [
+ {"resource": "ClaimResponse", "fhirPathCriteria": "use = 'preauthorization'"}
+ ]
+}
+```
+{% endcode %}
+
+{% endstep %}
+{% step %}
+
+### Create the Subscription
+
+Create a standard FHIR R4B `Subscription` whose `criteria` is the topic `url` and whose `channel` is a rest-hook pointing at your endpoint. The R4B backport extensions select the payload content and an optional heartbeat.
+
+{% code title="PUT /Subscription/pas-claimresponse-sub" %}
+```json
+{
+ "resourceType": "Subscription",
+ "id": "pas-claimresponse-sub",
+ "status": "requested",
+ "reason": "Downstream PA decision notifications",
+ "criteria": "http://prior-auth.example.org/SubscriptionTopic/pas-claimresponse-status",
+ "channel": {
+ "type": "rest-hook",
+ "endpoint": "https://downstream.example.org/fhir/notifications",
+ "payload": "application/fhir+json",
+ "header": ["Authorization: Bearer "]
+ },
+ "extension": [
+ {
+ "url": "http://hl7.org/fhir/StructureDefinition/backport-payload-content",
+ "valueCode": "full-resource"
+ },
+ {
+ "url": "http://hl7.org/fhir/StructureDefinition/backport-heartbeat-period",
+ "valueUnsignedInt": 60
+ }
+ ]
+}
+```
+{% endcode %}
+
+| Field | Description |
+|---|---|
+| `criteria` (required) | The `AidboxSubscriptionTopic.url` to subscribe to. |
+| `channel.type` (required) | `rest-hook` — Aidbox POSTs each notification to the endpoint. |
+| `channel.endpoint` (required) | HTTPS URL that receives the notification bundle. Must answer the handshake with a `2xx`. |
+| `channel.payload` | MIME type of the delivered body, e.g. `application/fhir+json`. |
+| `channel.header` | Custom HTTP headers sent with every delivery — use for the subscriber's auth token. |
+| `backport-payload-content` | `full-resource` (whole resource), `id-only` (reference only), or `empty` (notification metadata only). |
+| `backport-heartbeat-period` | Seconds between empty keep-alive notifications during inactivity. Omit to disable. |
+
+{% hint style="warning" %}
+The endpoint must be reachable and return `2xx` to the handshake, or the subscription never leaves `requested` and no events are delivered.
+{% endhint %}
+
+{% endstep %}
+{% step %}
+
+### Verify
+
+On create, confirm the subscription reached `active` (`GET /Subscription/pas-claimresponse-sub` → `status`). Then trigger a matching write and confirm the bundle arrives at your endpoint — its first entry is a `SubscriptionStatus`, followed by the `ClaimResponse`.
+
+{% endstep %}
+{% endstepper %}
+
+## The notification bundle
+
+With `backport-payload-content: full-resource`, each delivery carries the complete triggering resource. For Prior Auth this is the `ClaimResponse` whose `reviewAction` extension conveys the decision (e.g. X12 `A1` = certified, `A3` = not certified, `A4` = pended — see [PAS](pas.md)). A subscriber that needs the full referenced context (Claim, Patient, Coverage) can resolve those references against the FHIR API, or use the AWS SNS extension below, which can ship them pre-resolved.
+
+## Provisioning at deploy time
+
+In production these resources are created from an init-bundle rather than by hand, with environment-variable substitution for environment-specific values (endpoint URL, auth token). One ordering rule applies: a subscription topic must exist before any `Subscription` that references its `url`.
+
+## AWS SNS delivery (Payerbox extension)
+
+Some deployments need events delivered to **AWS SNS** rather than a rest-hook endpoint — for example, fanning a PA decision out to an existing SQS/SNS pipeline. For these, Payerbox ships a set of custom `AidboxTopicDestination` kinds (`custom-aws-sns-at-least-once`, `custom-aws-sns-best-effort`, and a PAS-specific `pas-rest-hook-at-least-once` that assembles a Da Vinci PAS Response Bundle). They reuse the same `AidboxSubscriptionTopic` trigger but replace the standard `Subscription` with an `AidboxTopicDestination` sink, and can optionally enrich the payload with the triggering resource's referenced resources.
+
+This is a Payerbox extension provisioned per integration, not part of the standard FHIR subscription path above. Two operational notes carry over from `AidboxTopicDestination`:
+
+- **Custom profiles must be whitelisted.** The `custom-aws-sns-*` profiles are added to the `AidboxTopicDestination` `allow-destinations` constraint before any destination using them is created.
+- **Destinations are immutable.** Aidbox rejects `PUT`/`PATCH` on an existing `AidboxTopicDestination`; to change a target (ARN, region) delete and re-create it.
+
+If your deployment uses this extension, ask your Payerbox contact for the destination configuration reference.
+
+## Gotchas
+
+- **Handlers must be idempotent.** At-least-once delivery can repeat an event. Deduplicate on the resource id and version, or guard with your own idempotency key.
+- **Updates re-fire.** The topic fires on every interaction matching the criterion, including writes your own subscriber makes back into Aidbox. Avoid feedback loops when subscribing to a resource your downstream also updates.
+- **A subscription stuck in `requested` is not delivering.** It means the handshake never got a `2xx` — check endpoint reachability, TLS, and auth headers.
+
+## Related
+
+{% content-ref url="pas.md" %}
+[pas.md](pas.md)
+{% endcontent-ref %}
+
+{% content-ref url="../run-payerbox/maintain/observability.md" %}
+[observability.md](../run-payerbox/maintain/observability.md)
+{% endcontent-ref %}
diff --git a/docs/prior-auth/pas.md b/docs/prior-auth/pas.md
index dde51a1..05d6c4f 100644
--- a/docs/prior-auth/pas.md
+++ b/docs/prior-auth/pas.md
@@ -70,3 +70,7 @@ Accept: application/json
{% endtabs %}
Full Bundle profiles, all parameters, and edge cases: [Claim/$submit](../api-reference/operations/claim-submit.md). For status checks and attachment workflows: [Claim/$inquire](../api-reference/operations/claim-inquire.md), [$submit-attachment](../api-reference/operations/submit-attachment.md).
+
+## Notifications
+
+Rather than polling `Claim/$inquire`, a downstream system can subscribe to decision events and be notified when a `ClaimResponse` is recorded. See [Event Notifications](event-notifications.md) for how to set up a FHIR topic-based subscription.
diff --git a/docs/run-payerbox/maintain/README.md b/docs/run-payerbox/maintain/README.md
index 3adb4d4..48fbda7 100644
--- a/docs/run-payerbox/maintain/README.md
+++ b/docs/run-payerbox/maintain/README.md
@@ -5,5 +5,6 @@ Day-2 operations for a running Payerbox deployment.
| Page | What it covers |
|---|---|
| [Observability](observability.md) | Prometheus metrics, BALP audit logs, runbooks |
-| [Event Notifications](event-notifications.md) | Push FHIR events to AWS SNS or webhooks via topic-based subscriptions |
| [Upgrade](upgrade.md) | Bundle and per-image upgrade, breaking changes, rollback |
+
+Event notifications (FHIR topic-based subscriptions) are documented under [Prior Auth / Event Notifications](../../prior-auth/event-notifications.md).
diff --git a/docs/run-payerbox/maintain/event-notifications.md b/docs/run-payerbox/maintain/event-notifications.md
deleted file mode 100644
index 4b9692c..0000000
--- a/docs/run-payerbox/maintain/event-notifications.md
+++ /dev/null
@@ -1,241 +0,0 @@
----
-description: >-
- Push FHIR resource events from Payerbox to AWS SNS or HTTP webhooks using
- Aidbox topic-based subscriptions — triggers, destinations, and how to
- configure them.
----
-
-# Event Notifications
-
-Payerbox can push FHIR resource events to external systems as they happen — for example, notifying a downstream system the moment a prior-authorization decision is recorded. It is built on Aidbox **topic-based subscriptions** and configured entirely through FHIR resources. For where this sits in the stack, see [Architecture](../architecture.md).
-
-## How it works
-
-Two resources work together:
-
-| Resource | Role |
-|---|---|
-| `AidboxSubscriptionTopic` | The trigger — which resource type, an optional FHIRPath criterion, and which interactions (create / update / delete) fire it. |
-| `AidboxTopicDestination` | The sink — where matching events go. Its `kind` selects the transport (AWS SNS or HTTP webhook); `content` controls the payload shape. |
-
-When a CRUD operation matches a topic's trigger, the engine writes one event per bound destination. Senders drain those events asynchronously, so a slow or unavailable subscriber never blocks the originating FHIR write.
-
-```mermaid
-graph LR
- W(FHIR write
create / update / delete):::blue2 --> T(AidboxSubscriptionTopic
trigger + FHIRPath):::blue2
- T --> D(AidboxTopicDestination
SNS or webhook):::blue2
- D --> E(External system
SNS topic / HTTP endpoint):::green2
-```
-
-### Delivery guarantees
-
-Two delivery modes are available, selected by the destination `kind`:
-
-- **At-least-once** — events are persisted to a database queue and retried until acknowledged. A subscriber may see the same event more than once, so handlers must be idempotent. Use this whenever a missed notification matters (claim and decision notifications).
-- **Best-effort** — fire-and-forget. Lower latency, no retry. Use only where an occasional drop is acceptable.
-
-## Destination kinds
-
-| `kind` | Transport | Profile (`meta.profile`) |
-|---|---|---|
-| `webhook-at-least-once` | HTTP POST to an endpoint | `http://aidbox.app/StructureDefinition/aidboxtopicdestination-webhook-at-least-once` |
-| `aws-sns-at-least-once` | AWS SNS, queued + retried | `http://aidbox.app/StructureDefinition/aidboxtopicdestination-aws-sns-at-least-once` |
-| `aws-sns-best-effort` | AWS SNS, fire-and-forget | `http://aidbox.app/StructureDefinition/aidboxtopicdestination-aws-sns-best-effort` |
-| `custom-aws-sns-at-least-once` | AWS SNS, queued + retried, with reference enrichment | `http://health-samurai.io/fhir/core/StructureDefinition/aidboxtopicdestination-customAWSSNSAtLeastOnceProfile` |
-| `custom-aws-sns-best-effort` | AWS SNS, fire-and-forget, with reference enrichment | `http://health-samurai.io/fhir/core/StructureDefinition/aidboxtopicdestination-customAWSSNSBestEffortProfile` |
-
-The `custom-aws-sns-*` kinds are a Payerbox extension of the AWS SNS senders. When the `aidboxUrl` and `aidboxAuth` parameters are set, the sender resolves the triggering resource's references and ships an enriched payload instead of the bare resource; without those parameters they behave exactly like the plain `aws-sns-*` kinds.
-
-The `webhook-at-least-once` kind and the plain `aws-sns-*` kinds are shipped by Aidbox and accepted out of the box. The `custom-aws-sns-*` kinds use Payerbox-specific profiles that must be whitelisted first — see [step 1](#whitelist-the-destination-profile).
-
-## Prerequisites
-
-- Admin access to Aidbox to create the resources below (root client or the admin API).
-- A delivery target: for SNS, a topic ARN and either an IAM role on the Aidbox workload or explicit AWS credentials; for a webhook, a reachable HTTP endpoint.
-
-## Configure a notification
-
-Create the resources below with admin credentials. In production they are usually provisioned from an init-bundle — see [Provisioning at deploy time](#provisioning-at-deploy-time).
-
-{% stepper %}
-{% step %}
-
-### Whitelist the destination profile
-
-`AidboxTopicDestination` is constrained by an `allow-destinations` rule listing the accepted `meta.profile` URLs. Built-in kinds (`webhook-at-least-once`, `aws-sns-*`) are already on this list — skip to [step 2](#define-the-subscription-topic) if you use one of them. The Payerbox `custom-aws-sns-*` profiles are not, so they must be added **before** any destination that uses them is created, or the destination is rejected.
-
-Patch the constraint to include the custom profile URL:
-
-{% code title="PATCH /fhir/StructureDefinition/AidboxTopicDestination" %}
-```json
-{
- "resourceType": "Parameters",
- "parameter": [
- {
- "name": "operation",
- "part": [
- {"name": "type", "valueCode": "add"},
- {"name": "path", "valueString": "differential.element.where(id='AidboxTopicDestination.meta.profile').binding.extension.valueSet"},
- {"name": "value", "valueUri": "http://health-samurai.io/fhir/core/StructureDefinition/aidboxtopicdestination-customAWSSNSAtLeastOnceProfile"}
- ]
- }
- ]
-}
-```
-{% endcode %}
-
-The list is additive — repeat the PATCH with the `customAWSSNSBestEffortProfile` URL if you use the best-effort variant.
-
-{% endstep %}
-{% step %}
-
-### Define the subscription topic
-
-Declare what to notify on. The `trigger.fhirPathCriteria` narrows the firing condition; omit it to fire on every interaction of the resource type.
-
-{% code title="PUT /AidboxSubscriptionTopic/pas-claimresponse-status" %}
-```json
-{
- "resourceType": "AidboxSubscriptionTopic",
- "id": "pas-claimresponse-status",
- "url": "http://prior-auth.example.org/SubscriptionTopic/pas-claimresponse-status",
- "status": "active",
- "description": "Notify when PAS ClaimResponses are created or updated",
- "trigger": [
- {"resource": "ClaimResponse", "fhirPathCriteria": "use = 'preauthorization'"}
- ]
-}
-```
-{% endcode %}
-
-{% endstep %}
-{% step %}
-
-### Create the topic destination
-
-Bind a destination to the topic's `url`. Pick the tab that matches your transport.
-
-{% tabs %}
-{% tab title="AWS SNS" %}
-{% code title="PUT /AidboxTopicDestination/pas-claimresponse-sns" %}
-```json
-{
- "resourceType": "AidboxTopicDestination",
- "id": "pas-claimresponse-sns",
- "kind": "custom-aws-sns-at-least-once",
- "meta": {
- "profile": ["http://health-samurai.io/fhir/core/StructureDefinition/aidboxtopicdestination-customAWSSNSAtLeastOnceProfile"]
- },
- "status": "active",
- "topic": "http://prior-auth.example.org/SubscriptionTopic/pas-claimresponse-status",
- "parameter": [
- {"name": "topicArn", "valueString": "arn:aws:sns:us-east-1:123456789012:pas-claimresponse"},
- {"name": "region", "valueString": "us-east-1"},
- {"name": "batchSize", "valueInteger": 1}
- ],
- "content": "full-resource"
-}
-```
-{% endcode %}
-
-| Parameter | Description |
-|---|---|
-| `topicArn` (required) | Target SNS topic ARN. For a FIFO topic (ARN ends in `.fifo`), also set `messageGroupId`. |
-| `region` (required) | AWS region, e.g. `us-east-1`. |
-| `accessKeyId`, `secretAccessKey` | Explicit credentials. If omitted, the default AWS credential chain is used (IAM role, environment, etc.). `secretAccessKey` is required when `accessKeyId` is set. |
-| `endpointOverride` | Alternate SNS endpoint URL — used for local testing against an SNS emulator. |
-| `messageGroupId` | Required when the topic ARN ends in `.fifo`. |
-| `batchSize` | At-least-once only; 1–10. Events published per batch. Default `1`. |
-| `aidboxUrl`, `aidboxAuth` | `custom-aws-sns-*` kinds only. Set both to enable reference enrichment; `aidboxAuth` is `username:password` for Basic auth. |
-
-{% hint style="warning" %}
-Prefer the default credential chain (an IAM role on the Aidbox workload) in production. Avoid storing a long-lived `secretAccessKey` in the destination resource.
-{% endhint %}
-{% endtab %}
-
-{% tab title="HTTP webhook" %}
-{% code title="PUT /AidboxTopicDestination/pas-claimresponse-webhook" %}
-```json
-{
- "resourceType": "AidboxTopicDestination",
- "id": "pas-claimresponse-webhook",
- "kind": "webhook-at-least-once",
- "meta": {
- "profile": ["http://aidbox.app/StructureDefinition/aidboxtopicdestination-webhook-at-least-once"]
- },
- "status": "active",
- "topic": "http://prior-auth.example.org/SubscriptionTopic/pas-claimresponse-status",
- "parameter": [
- {"name": "endpoint", "valueUrl": "https://downstream.example.org/webhooks/claimresponse"},
- {"name": "timeout", "valueUnsignedInt": 5000}
- ],
- "content": "full-resource"
-}
-```
-{% endcode %}
-
-| Parameter | Description |
-|---|---|
-| `endpoint` (required) | Target URL the event is POSTed to. |
-| `timeout` | Per-delivery timeout in milliseconds. |
-
-If the endpoint requires Basic auth, configure the corresponding Aidbox client with `grant_types: ["basic"]`.
-{% endtab %}
-{% endtabs %}
-
-`content: "full-resource"` ships the complete triggering resource in the notification. With a `custom-aws-sns-*` kind and `aidboxUrl`/`aidboxAuth` set, the payload additionally carries the resolved referenced resources.
-
-{% endstep %}
-{% step %}
-
-### Verify
-
-Trigger a matching write and confirm delivery downstream — for SNS, watch the topic's `NumberOfMessagesPublished` metric; for a webhook, check the receiver's logs.
-
-{% hint style="info" %}
-Don't rely on the internal event queue to confirm activity: the at-least-once queue is drained and the row deleted on successful delivery, so a healthy pipeline shows an empty queue within seconds.
-{% endhint %}
-
-{% endstep %}
-{% endstepper %}
-
-## Provisioning at deploy time
-
-In production these resources are created from an init-bundle rather than by hand, with environment-variable substitution for environment-specific values (topic ARN, region, credentials). Two ordering rules apply:
-
-- The `allow-destinations` whitelist PATCH must come **before** any destination that uses a custom profile.
-- A subscription topic must exist before the destinations that reference its `url`.
-
-## Updating a destination
-
-{% hint style="warning" %}
-`AidboxTopicDestination` resources are **immutable** — Aidbox rejects `PUT` and `PATCH` on an existing destination. To change one (a new ARN, a different endpoint), **delete and re-create** it.
-{% endhint %}
-
-Re-creation is also what registers the destination with the in-memory delivery engine. A destination that exists in the database but was never created against a running engine — for example, an init-bundle entry that was a no-op because the resource already existed — will not deliver events. If a topic stops firing after a restart, delete and re-create the destination to force re-registration.
-
-## Gotchas
-
-- **Handlers must be idempotent.** At-least-once delivery can repeat an event. Deduplicate on the resource id and version, or guard with your own idempotency key.
-- **Updates re-fire.** The engine fires on every interaction matching the criterion, including writes your own subscriber makes back into Aidbox. Avoid feedback loops when subscribing to a resource your downstream also updates.
-- **Stale configuration does not self-correct.** Because destinations are immutable and init-bundles commonly create them only when absent, a wrong value set at first boot persists silently. Re-create the destination to fix it.
-
-## Current limitations
-
-- Destinations cannot be edited in place — every change is delete-and-re-create.
-- There is no built-in dead-letter queue; an at-least-once event retries until delivered.
-- Reference enrichment is available only on the `custom-aws-sns-*` kinds, not on webhooks.
-
-## Related
-
-{% content-ref url="observability.md" %}
-[observability.md](observability.md)
-{% endcontent-ref %}
-
-{% content-ref url="../architecture.md" %}
-[architecture.md](../architecture.md)
-{% endcontent-ref %}
-
-{% content-ref url="../../prior-auth/pas.md" %}
-[pas.md](../../prior-auth/pas.md)
-{% endcontent-ref %}
diff --git a/redirects.yaml b/redirects.yaml
new file mode 100644
index 0000000..172f056
--- /dev/null
+++ b/redirects.yaml
@@ -0,0 +1,2 @@
+redirects:
+ run-payerbox/maintain/event-notifications.md: prior-auth/event-notifications.md