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

# Enrollment

> Learn how to enroll an employer group and track onboarding through activation.

Enrollment is the moment the employer commits: you lock their selection against a quote, and Prescience provisions the company and runs onboarding with them directly. It is your last required API call in the launch flow.

## Create an enrollment

```bash theme={null}
curl -X POST https://www.getprescience.com/api/partner/v1/groups/grp_8c2f41d09a3e/enrollments \
  -H "Authorization: Bearer $PRESCIENCE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: enroll-acme-1" \
  -d '{
    "quoteId": "qt_5b9e2c7f10ad",
    "startDate": "2026-09-01",
    "signatory": { "name": "Dana Park", "email": "dana@acme.com", "title": "Head of People" }
  }'
```

| Field            | Type                         | Required | Description                                                                                                                                                                                                              |
| ---------------- | ---------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `quoteId`        | string                       | **Yes**  | The quote the employer accepted. Must be `ready` and unexpired.                                                                                                                                                          |
| `startDate`      | date (`YYYY-MM-DD`)          | No       | Defaults to the quote's `planYearStartDate`.                                                                                                                                                                             |
| `signatory`      | object                       | **Yes**  | The employer admin who selected the plan: `name` (required), `email` (required, valid address), `title` (optional). On the hosted pathway they are provisioned as the company's admin in the Prescience employer portal. |
| `onboardingMode` | enum: `hosted` \| `embedded` | No       | How post-enrollment onboarding runs. Defaults to `hosted`. See [onboarding pathways](#onboarding-pathways).                                                                                                              |

<Tip>
  Always send an `Idempotency-Key` on enrollment; it's the one call you really don't want duplicated on a network retry. Replays within 24 hours return the stored response.
</Tip>

## Onboarding pathways

### Hosted (default)

With `onboardingMode: "hosted"`, all post-enrollment onboarding runs in the Prescience employer portal. At enrollment, Prescience provisions the signatory as an employer portal admin for the company; in live mode they receive a set-password invite email pointing at the portal sign-in. Prescience then runs onboarding, KYB, banking, and plan setup with the employer directly. Your integration tracks progress by polling [`GET /enrollments/{enrollmentId}`](#track-onboarding-to-activation) or listening to [webhooks](/guides/webhooks); there is nothing for you to render beyond status.

The response reports what was provisioned in the `employerPortal` object:

| Field              | Type    | Description                                                                                                                                           |
| ------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provisioned`      | boolean | Whether the signatory's portal account was created. `false` indicates a provisioning failure; the enrollment itself stands and Prescience follows up. |
| `signinUrl`        | string  | The employer portal sign-in URL, suitable for a "Manage in Prescience" link in your UI.                                                               |
| `inviteSuppressed` | boolean | `true` when no invite email was sent. Always `true` in test mode: test mode never sends outbound email, while the account is still provisioned.       |

### Embedded

Embedded onboarding keeps onboarding forms, document e-signature, and banking capture inside your own UI. It is separate from the core hosted flow and is enabled per integration.

## Validations

Each check has a distinct failure mode:

| Check                                                               | Failure                                                            | Your handling                                                                                         |
| ------------------------------------------------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
| Quote exists in this group and mode                                 | `404 not_found`                                                    | Verify the `quoteId` and the key's mode.                                                              |
| Quote is unexpired                                                  | `410 quote_expired`                                                | Re-quote (deterministic; an unchanged census re-prices identically) and retry with the new `quoteId`. |
| Quote is not `in_review`                                            | `409 conflict`                                                     | Wait for the [`quote.finalized` webhook](/guides/webhooks#event-catalog), then retry.                 |
| Census has active members                                           | `422 census_required`                                              | `PUT /census` first.                                                                                  |
| Census is enrollment-ready                                          | `400 invalid_request` with per-member `details` (`index`, `field`) | Collect the missing `firstName` / `lastName` / `email` values, re-`PUT` the census, retry.            |
| No existing active enrollment, and no enrolled group on this domain | `409 conflict`                                                     | The employer is already enrolled; treat as success and reconcile state.                               |

Details on enrollment-readiness in the [census guide](/guides/census#quoting-vs-enrollment-requirements).

## What happens when you POST

All of it synchronous with the `201`:

1. **Provisions the company** for `group.domain` in `sandbox` state, with the signatory as admin.
2. **Materializes the census** into live plan records: members and dependents, upserted by email.
3. **Provisions the signatory's portal account** (hosted pathway) and, in live mode, sends the set-password invite. Test mode provisions without sending email.
4. **Moves the group to `enrolled`** and fires the [`enrollment.created` webhook](/guides/webhooks#event-catalog).
5. **Starts the onboarding pipeline.** The human side begins here.

## The Enrollment object

```json Response (201) theme={null}
{
  "id": "enr_3f7a92c81b40",
  "groupId": "grp_8c2f41d09a3e",
  "mode": "test",
  "status": "onboarding",
  "quoteId": "qt_5b9e2c7f10ad",
  "startDate": "2026-09-01",
  "companyDomain": "acme.com",
  "companyState": "sandbox",
  "onboardingMode": "hosted",
  "employerPortal": {
    "provisioned": true,
    "signinUrl": "https://www.getprescience.com/signin",
    "inviteSuppressed": true
  },
  "onboarding": { "percentComplete": 0, "blockingRemaining": 0 },
  "nextSteps": [
    "Prescience onboarding call scheduled with the employer",
    "Employer completes KYB + plan setup in the Prescience portal",
    "Prescience activates the group (state → prod)"
  ],
  "createdAt": "2026-06-12T09:14:32Z"
}
```

| Field                           | Type                              | Description                                                                                                        |
| ------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `id`                            | string                            | Enrollment ID (`enr_` prefix).                                                                                     |
| `status`                        | enum: `onboarding` \| `active`    | `active` once Prescience activates the company to `prod`.                                                          |
| `quoteId`, `startDate`          | string, date                      | The locked selection.                                                                                              |
| `companyDomain`, `companyState` | string, enum: `sandbox` \| `prod` | The provisioned company and its state.                                                                             |
| `onboardingMode`                | enum: `hosted` \| `embedded`      | Stamped at creation.                                                                                               |
| `employerPortal`                | object                            | Present when the signatory was provisioned (always on the hosted pathway). See [above](#hosted-default).           |
| `onboarding`                    | object                            | `percentComplete` (0 to 100) and `blockingRemaining`, recomputed from the live onboarding checklist on every read. |
| `nextSteps`                     | string\[]                         | Display-ready; render it as the employer-facing status checklist.                                                  |

This example is a test-mode enrollment, so `inviteSuppressed` is `true`: the portal account exists, but no email went out.

## Track onboarding to activation

```mermaid theme={null}
stateDiagram-v2
    direction LR
    [*] --> sandbox : POST /enrollments
    sandbox --> prod : Prescience activates<br/>(onboarding complete)
    prod --> [*]

    note right of sandbox
        enrollment.status = onboarding
        group.status = enrolled
        No money movement
    end note

    note right of prod
        enrollment.status = active
        group.status = active
        Plan in force, funding live
    end note
```

The company starts in `sandbox`: fully configured, no money moving. Prescience runs onboarding with the employer (kickoff call, KYB, plan setup in the portal) and then flips the company to `prod`. That flip is a manual gate on our side; it is what makes the plan real.

Track progress two ways:

* **Poll** `GET /groups/{groupId}/enrollments/{enrollmentId}`: `onboarding.percentComplete` and `blockingRemaining` are recomputed from the live onboarding checklist on every read.
* **Listen** for [`group.state_changed`](/guides/webhooks#event-catalog), fired on `sandbox → prod` with the old and new state.

When the company reaches `prod`, `enrollment.status` becomes `active`, `group.status` becomes `active`, and the [benefits tab](/guides/benefits-tab) starts showing real funding and spend.

In test mode the pipeline behaves identically except the final flip: test companies are flagged `test: true` and are never moved to `prod`. See [Environments](/test-mode).

## What you build vs what you don't

| You build                                      | You don't build                                |
| ---------------------------------------------- | ---------------------------------------------- |
| The "Select plan" button → `POST /enrollments` | Underwriting sign-off                          |
| An "onboarding in progress" status surface     | KYB and employer verification                  |
| Webhook handler for activation                 | Plan documents, SBCs, compliance filings       |
|                                                | Funding setup and risk-protection coordination |
|                                                | Employee app invitations and care onboarding   |

The integration's job ends at the POST. Ours begins there.
