> ## 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.

# HIPAA BAA gate evaluation guide

> Understand when the HIPAA BAA gate evaluates a send, what a missing BAA record means, and how owners and admins verify the tenant's posture.

# HIPAA BAA gate evaluation

The HIPAA BAA gate is the send-time check that protects PHI traffic when your organization has declared PHI in scope. It evaluates the tenant's BAA record before a message is dispatched. This page focuses on the evaluation result, including the important difference between a tenant with a null BAA record and a tenant record that does not exist.

The BAA is a **tenant-owned record**. Devotel Orbit provides the gate and the execution flow; your organization decides whether PHI is in scope and an owner executes the agreement. See [Business Associate Agreement (BAA)](/compliance/baa) for the lifecycle.

***

## 1. Where the BAA gate runs in the send path

A send enters Orbit's compliance checks before sender resolution, wallet hold, quota increment, or provider dispatch. The BAA evaluation runs as part of that chain alongside the TCPA and consent checks. If the BAA gate blocks, the send stops before any provider receives it and the blocked send does not consume wallet balance or quota.

The response identifies a lifecycle block with `422 HIPAA_BAA_REQUIRED`. Its `details.reason` is one of:

* `pending` — the tenant has declared PHI in scope, but the BAA is awaiting execution.
* `expired` — the BAA has passed its one-year term.
* `not_signed` — the record is missing the state needed to prove an executed, in-term BAA.

A verification failure is different: `500 HIPAA_BAA_GATE_DB_FAIL` means Orbit could not validate the tenant record. That path also blocks the send and reports `verification_unavailable`; retry, then contact support if the error persists.

### Which audit entry should you look for?

The audit log records the tenant's BAA lifecycle actions, not a separate audit row for every predicate evaluation. In **Settings → Audit log**, look for these entries:

| Audit action | What it proves |
| - | - |
| `compliance.baa.hipaa_required` | An owner or admin attested that PHI is in scope. |
| `compliance.baa.executed` | An owner executed the BAA. This is the evidence that creates the tenant's signed record. |
| `compliance.baa.declined` | An owner or admin recorded that PHI is no longer in scope before execution. |
| `compliance.baa.reverted` | An owner returned an executed or expired agreement to the platform default after the required workflow. |

Use the audit action together with the current BAA response. An `executed` audit event alone does not keep sends open forever: the gate rechecks the current status and execution timestamp at send time.

***

## 2. What a null BAA record produces

For a tenant with `hipaa_required: true`, a null BAA value does not mean "unknown but allowed." It means the gate cannot prove that an executed BAA is in term, so it blocks with `not_signed`.

The evaluation uses three values:

| Tenant values | Evaluation |
| - | - |
| `hipaa_required` is not `true` | Not blocked. The BAA gate is a no-op because PHI is not in scope. |
| `hipaa_required: true`, `baa_status: null`, `baa_executed_at: null` | Blocked with `not_signed`, returned as `422 HIPAA_BAA_REQUIRED`. |
| `hipaa_required: true`, `baa_status: "pending"` | Blocked with `pending`. |
| `hipaa_required: true`, `baa_status: "executed"`, with a valid in-term timestamp | Not blocked. |
| `hipaa_required: true`, `baa_status: "executed"`, with a missing, malformed, or future timestamp | Blocked with `not_signed`. |
| `hipaa_required: true`, an executed timestamp older than one year, or `baa_status: "expired"` | Blocked with `expired`. |

This is a fail-closed decision for the tenant-owned BAA record: a null status or timestamp cannot establish coverage. The gate re-derives the one-year term from `baa_executed_at`, so a delayed expiry update does not leave a lapsed BAA open.

There is one separate case. If no organization row is found at all, the request has no tenant record to evaluate and the internal guard returns without a BAA decision. That is different from a present organization row whose BAA fields are null. Do not treat a missing organization as an alternative way to clear the gate.

The evaluation behavior is pinned by the `evaluate-baa-send-gate` test in the API compliance library. That test covers the null BAA state, the `pending` state, valid execution, locally derived expiry, and malformed or future timestamps. Keep this page aligned with that test when the gate contract changes.

***

## 3. How to verify your BAA posture

1. Open **Settings → Compliance → BAA**, or call `GET /api/v1/compliance/baa`.
2. Confirm that `hipaa_required` is `true` only when your organization handles PHI.
3. For PHI sends, confirm `baa_status` is `executed` and `baa_executed_at` is present and current.
4. Check `expires_at` and the audit log entry `compliance.baa.executed` together. The audit entry shows who executed the agreement; the current status and timestamp show whether the send-time gate will pass now.
5. If a send returns `HIPAA_BAA_REQUIRED`, use `details.reason` to choose the next action. Execute a pending BAA, re-execute an expired BAA, or correct the tenant's unsigned record. If the reason is `verification_unavailable`, treat it as a verification outage rather than as proof that the BAA is unsigned.

Execution is owner-only. Admins can read the posture and manage the PHI-in-scope attestation, but an owner must execute or revert the agreement. The audit chain is tenant-scoped and gives your compliance reviewers the actor and action history without changing the platform's evaluation rule.

***

## 4. How PHI-adjacent audiences affect evaluation

The [PHI-adjacent audience registry](/compliance/phi-audiences) identifies contact-list and segment ids whose members may carry PHI. When HIPAA is in scope and a campaign uses a designated audience, the campaign launch precheck evaluates the same BAA state before enrollment. A null or otherwise unsigned BAA record therefore blocks the launch with `HIPAA_BAA_REQUIRED`, just as it blocks a per-recipient send.

Audiences assembled without a registered list or segment id are evaluated at send time. Register an audience only when its members may carry PHI; the designation is tenant-owned and does not execute or replace the BAA.

***

## 5. Tenant-owned framing

The BAA gate is a platform gate over a record your tenant provides. The platform evaluates the `hipaa_required` declaration, `baa_status`, and `baa_executed_at`; it does not decide whether your organization processes PHI or sign the agreement for you.

Once an owner executes the BAA, the tenant record is in place and the gate can pass while the agreement remains in term. You still own the posture: keep the declaration accurate, review the audit log, designate PHI-adjacent audiences, and re-execute before expiry. The BAA gate is not the platform-global federal voice guard; that separate guard is the sole global compliance hard gate.

## Related pages

* [Business Associate Agreement (BAA)](/compliance/baa) — execute, download, re-execute, or revert the agreement.
* [Send gates](/compliance/send-gates#baa-the-hipaa-send-gate) — compare the BAA gate with other send-time checks.
* [PHI-adjacent audience designations](/compliance/phi-audiences) — register audiences that may carry PHI.
* [HIPAA compliance](/compliance/hipaa) — configure the broader tenant-owned HIPAA controls.

*Last updated: October 2026*


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.