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
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. |
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.
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} or listening to 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, 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.
What happens when you POST
All of it synchronous with the 201:
- Provisions the company for
group.domain in sandbox state, with the signatory as admin.
- Materializes the census into live plan records: members and dependents, upserted by email.
- Provisions the signatory’s portal account (hosted pathway) and, in live mode, sends the set-password invite. Test mode provisions without sending email.
- Moves the group to
enrolled and fires the enrollment.created webhook.
- Starts the onboarding pipeline. The human side begins here.
The Enrollment object
{
"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. |
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
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, 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 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.
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.