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

# PHI-adjacent audience designations

> Reference for the PHI-adjacent audience registry: what a designation attests, how GET lists and PUT replaces the designated id set, the server-side registry ceiling, and how the BAA gate and the HIPAA controls interact with it.

# PHI-adjacent audience designations

The PHI-adjacent audience registry is your organization's register of contact-list and segment ids whose members carry PHI. This page is the reference for the two registry endpoints: what a designation attests, how `GET` lists and `PUT` replaces the id set, the server-side ceiling on registry size, and how the BAA lifecycle and HIPAA controls interact with the registry. For a step-by-step walkthrough, see [Register PHI-adjacent audiences](/guides/hipaa-phi-audiences); for the full HIPAA control surface, see [HIPAA compliance](/compliance/hipaa).

<Note>
  The registry is a **tenant-owned** compliance control. You decide which
  audiences carry PHI; Orbit enforces the designations you set and never
  designates an audience on your behalf. Designations take effect only once
  HIPAA is in scope for your organization.
</Note>

***

## What a designation attests

Under HIPAA mode — once your organization has attested that PHI is in scope — a designated list or segment id tells the platform: *members of this audience may carry Protected Health Information (PHI).* The designation follows the audience itself, not any individual campaign: an audience is PHI-adjacent because of its source data (an EHR export, a treatment-outreach opt-in list), so every campaign that picks the audience up inherits the designation for as long as it stays in the registry.

The registry holds **audience id strings** — contact-list ids and segment ids, 1–128 characters each. Audiences assembled per contact (all contacts, CSV upload, manual entry) have no registry id to designate and are evaluated recipient-by-recipient at send time instead.

***

## List the registry (GET)

```bash theme={null}
GET /api/v1/compliance/hipaa/phi-audiences
```

Returns the organization's full designated id set — there is no pagination; the whole registry is returned in one response:

```json theme={null}
{
  "data": {
    "audience_ids": ["list_9f2c1a", "seg_4b7e20"],
    "max": 500
  }
}
```

The `max` field reports the **server-side registry-size ceiling**: at most **500 ids per organization**. Because the campaign launch precheck evaluates audiences against the registry, the ceiling is enforced write-side rather than by an ever-growing unbounded list.

Both endpoints require the `owner` or `admin` role — the same gate the [BAA endpoints](/compliance/baa) use. A `developer`, `viewer`, or `billing` role receives `403`.

To rederive the id you want to designate:

```bash theme={null}
GET /api/v1/contacts/lists      # contact lists
GET /api/v1/contacts/segments   # segments
```

Copy the `id` field of the list or segment you are designating.

***

## Replace the registry (PUT)

```bash theme={null}
PUT /api/v1/compliance/hipaa/phi-audiences
{
  "audience_ids": ["list_9f2c1a", "seg_4b7e20"]
}
```

`PUT` is a **full replacement** of the designated id set — one write operation, no `PATCH`, no per-id `DELETE`. The write commits atomically in a single statement, so a concurrent `GET` never sees a partially applied update. The response echoes the stored set with a write-acknowledgement flag:

```json theme={null}
{
  "data": {
    "audience_ids": ["list_9f2c1a", "seg_4b7e20"],
    "replaced": true
  }
}
```

Because the write is a swap, every client must follow **read-modify-write**: `GET` the current registry, add or remove your id in the result, and `PUT` the whole set back. Building the body from local state alone silently drops designations another operator added.

To lift a designation, `PUT` the registry without that id; to re-designate, `PUT` it with the id added back. An empty array clears every designation:

```bash theme={null}
PUT /api/v1/compliance/hipaa/phi-audiences
{
  "audience_ids": []
}
```

Validation failures return `422`: more than 500 ids, or an id that is empty after trimming or over 128 characters. Whitespace is trimmed server-side. The `audience_ids` field defaults to an empty array, so a request missing that field clears the registry rather than failing.

Every replacement is recorded in the organization's audit log as a `hipaa.phi_audiences.set` entry carrying the acting user and the full post-write id set. The sequence of `set` rows is the registry's version history — to reconstruct what was designated at a point in time, walk the rows back.

***

## Interaction with the BAA gate

Designation feeds the **campaign launch precheck**: when HIPAA is in scope for your organization and a campaign's audience resolves to a designated list or segment id, the launch is refused with `422 HIPAA_BAA_REQUIRED` until your BAA is `executed` and in-term. The precheck evaluates the same BAA rules as the per-recipient send gate, so the two never disagree about what "BAA in-term" means. Neither gate fires until HIPAA is in scope — a designation on a workspace that has not attested PHI is inert.

The BAA lifecycle — `require`, `execute`, `decline`, `revert`, and the one-year term — is documented under [Business Associate Agreement (BAA)](/compliance/baa). The per-recipient send gate's verdicts and fail-closed behaviour are under [Send gates](/compliance/send-gates#baa-the-hipaa-send-gate). The healthcare workspace enable sequence is under [HIPAA compliance](/compliance/hipaa) and [HIPAA onboarding](/guides/hipaa-onboarding).

***

## Troubleshooting: `422 HIPAA_BAA_REQUIRED`

When a launch is refused because a designated audience meets a BAA that is not `executed` and in-term, the resolution paths — execute the BAA, or lift the designation if the audience genuinely carries no PHI — are mapped on the troubleshooting page: [Troubleshooting: HIPAA\_BAA\_REQUIRED (422)](/troubleshooting/phi-audience-baa-required). The check's `details.reason` (`not_signed`, `pending`, `expired`) tells you which BAA state de-blocks the launch.

***

## API reference

| Method | Endpoint                          | Description                                                                   | Required role     |
| ------ | --------------------------------- | ----------------------------------------------------------------------------- | ----------------- |
| `GET`  | `/compliance/hipaa/phi-audiences` | Read the full designated id set and the server-side ceiling (`max`)           | `owner` / `admin` |
| `PUT`  | `/compliance/hipaa/phi-audiences` | Full-replacement write of the designated id set (≤ 500 ids, each 1–128 chars) | `owner` / `admin` |

***

## See also

* [HIPAA compliance](/compliance/hipaa) — the full HIPAA control surface the registry feeds
* [Business Associate Agreement (BAA)](/compliance/baa) — the lifecycle the launch precheck enforces
* [Register PHI-adjacent audiences](/guides/hipaa-phi-audiences) — the production walkthrough (designation provenance, audit review cadence, concurrent-write mitigation)
* [Troubleshooting: HIPAA\_BAA\_REQUIRED (422)](/troubleshooting/phi-audience-baa-required) — resolve a blocked launch
* [Send gates](/compliance/send-gates) — the per-recipient gate that complements the launch precheck

***

*Last updated: September 2026*
*For questions about PHI-adjacent designations, contact: [compliance@devotel.io](mailto:compliance@devotel.io)*
