Skip to main content
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" }
  }'
FieldTypeRequiredDescription
quoteIdstringYesThe quote the employer accepted. Must be ready and unexpired.
startDatedate (YYYY-MM-DD)NoDefaults to the quote’s planYearStartDate.
signatoryobjectYesThe 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.
onboardingModeenum: hosted | embeddedNoHow 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:
FieldTypeDescription
provisionedbooleanWhether the signatory’s portal account was created. false indicates a provisioning failure; the enrollment itself stands and Prescience follows up.
signinUrlstringThe employer portal sign-in URL, suitable for a “Manage in Prescience” link in your UI.
inviteSuppressedbooleantrue 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:
CheckFailureYour handling
Quote exists in this group and mode404 not_foundVerify the quoteId and the key’s mode.
Quote is unexpired410 quote_expiredRe-quote (deterministic; an unchanged census re-prices identically) and retry with the new quoteId.
Quote is not in_review409 conflictWait for the quote.finalized webhook, then retry.
Census has active members422 census_requiredPUT /census first.
Census is enrollment-ready400 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 domain409 conflictThe 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:
  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.
  5. Starts the onboarding pipeline. The human side begins here.

The Enrollment object

Response (201)
{
  "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"
}
FieldTypeDescription
idstringEnrollment ID (enr_ prefix).
statusenum: onboarding | activeactive once Prescience activates the company to prod.
quoteId, startDatestring, dateThe locked selection.
companyDomain, companyStatestring, enum: sandbox | prodThe provisioned company and its state.
onboardingModeenum: hosted | embeddedStamped at creation.
employerPortalobjectPresent when the signatory was provisioned (always on the hosted pathway). See above.
onboardingobjectpercentComplete (0 to 100) and blockingRemaining, recomputed from the live onboarding checklist on every read.
nextStepsstring[]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 buildYou don’t build
The “Select plan” button → POST /enrollmentsUnderwriting sign-off
An “onboarding in progress” status surfaceKYB and employer verification
Webhook handler for activationPlan 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.