curl --request POST \
--url https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"quoteId": "qt_5b9e2c7f10ad",
"signatory": {
"name": "Dana Park",
"email": "dana@acme.com",
"title": "Head of People"
}
}
'import requests
url = "https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments"
payload = {
"quoteId": "qt_5b9e2c7f10ad",
"signatory": {
"name": "Dana Park",
"email": "dana@acme.com",
"title": "Head of People"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
quoteId: 'qt_5b9e2c7f10ad',
signatory: {name: 'Dana Park', email: 'dana@acme.com', title: 'Head of People'}
})
};
fetch('https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'quoteId' => 'qt_5b9e2c7f10ad',
'signatory' => [
'name' => 'Dana Park',
'email' => 'dana@acme.com',
'title' => 'Head of People'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments"
payload := strings.NewReader("{\n \"quoteId\": \"qt_5b9e2c7f10ad\",\n \"signatory\": {\n \"name\": \"Dana Park\",\n \"email\": \"dana@acme.com\",\n \"title\": \"Head of People\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"quoteId\": \"qt_5b9e2c7f10ad\",\n \"signatory\": {\n \"name\": \"Dana Park\",\n \"email\": \"dana@acme.com\",\n \"title\": \"Head of People\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"quoteId\": \"qt_5b9e2c7f10ad\",\n \"signatory\": {\n \"name\": \"Dana Park\",\n \"email\": \"dana@acme.com\",\n \"title\": \"Head of People\"\n }\n}"
response = http.request(request)
puts response.read_body{
"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"
}{
"error": "invalid_request",
"message": "2 members are missing fields required for enrollment.",
"details": [
{
"field": "email",
"message": "email is required for enrollment",
"index": 3
},
{
"field": "lastName",
"message": "lastName is required for enrollment",
"index": 9
}
]
}{
"error": "unauthorized",
"message": "Provide a valid partner API key as `Authorization: Bearer psk_...`."
}{
"error": "not_found",
"message": "No group grp_8c2f41d09a3e found."
}{
"error": "conflict",
"message": "Group grp_8c2f41d09a3e already has an active enrollment."
}{
"error": "quote_expired",
"message": "Quote qt_5b9e2c7f10ad expired on 2026-07-10. Create a new quote."
}{
"error": "rate_limited",
"message": "Rate limit exceeded. Retry after 12 seconds."
}{
"error": "server_error",
"message": "Internal error. The request was not applied."
}Create an enrollment
Locks the employer’s plan selection against a quote. Requires an unexpired ready quote and an enrollment-ready census: every active member needs firstName, lastName, and email (failures come back as invalid_request with per-member details). Prescience provisions the company (state sandbox), materializes the census, and starts the onboarding pipeline. On the hosted pathway (default) the signatory is also provisioned as an employer portal admin and receives a set-password invite; in test mode the invite email is suppressed (employerPortal.inviteSuppressed: true). Fires the enrollment.created webhook.
curl --request POST \
--url https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"quoteId": "qt_5b9e2c7f10ad",
"signatory": {
"name": "Dana Park",
"email": "dana@acme.com",
"title": "Head of People"
}
}
'import requests
url = "https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments"
payload = {
"quoteId": "qt_5b9e2c7f10ad",
"signatory": {
"name": "Dana Park",
"email": "dana@acme.com",
"title": "Head of People"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
quoteId: 'qt_5b9e2c7f10ad',
signatory: {name: 'Dana Park', email: 'dana@acme.com', title: 'Head of People'}
})
};
fetch('https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'quoteId' => 'qt_5b9e2c7f10ad',
'signatory' => [
'name' => 'Dana Park',
'email' => 'dana@acme.com',
'title' => 'Head of People'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments"
payload := strings.NewReader("{\n \"quoteId\": \"qt_5b9e2c7f10ad\",\n \"signatory\": {\n \"name\": \"Dana Park\",\n \"email\": \"dana@acme.com\",\n \"title\": \"Head of People\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"quoteId\": \"qt_5b9e2c7f10ad\",\n \"signatory\": {\n \"name\": \"Dana Park\",\n \"email\": \"dana@acme.com\",\n \"title\": \"Head of People\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.getprescience.com/api/partner/v1/groups/{groupId}/enrollments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"quoteId\": \"qt_5b9e2c7f10ad\",\n \"signatory\": {\n \"name\": \"Dana Park\",\n \"email\": \"dana@acme.com\",\n \"title\": \"Head of People\"\n }\n}"
response = http.request(request)
puts response.read_body{
"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"
}{
"error": "invalid_request",
"message": "2 members are missing fields required for enrollment.",
"details": [
{
"field": "email",
"message": "email is required for enrollment",
"index": 3
},
{
"field": "lastName",
"message": "lastName is required for enrollment",
"index": 9
}
]
}{
"error": "unauthorized",
"message": "Provide a valid partner API key as `Authorization: Bearer psk_...`."
}{
"error": "not_found",
"message": "No group grp_8c2f41d09a3e found."
}{
"error": "conflict",
"message": "Group grp_8c2f41d09a3e already has an active enrollment."
}{
"error": "quote_expired",
"message": "Quote qt_5b9e2c7f10ad expired on 2026-07-10. Create a new quote."
}{
"error": "rate_limited",
"message": "Rate limit exceeded. Retry after 12 seconds."
}{
"error": "server_error",
"message": "Internal error. The request was not applied."
}Authorizations
Partner API key. psk_test_<32 hex> for test mode, psk_live_<32 hex> for live mode. Keys are stored hashed and cannot be recovered; store them in your secrets manager on issue.
Headers
Any unique string (UUIDs work well). Replaying the same key within 24 hours returns the stored response instead of re-executing the request.
255Path Parameters
Group ID, e.g. grp_8c2f41d09a3e.
^grp_[0-9a-f]{12}$Body
"qt_5b9e2c7f10ad"
The employer admin who selected the plan. On the hosted pathway, provisioned as the company's admin in the Prescience employer portal.
Show child attributes
Show child attributes
Defaults to the quote's planYearStartDate.
"2026-09-01"
How post-enrollment onboarding runs. hosted (default): Prescience provisions the signatory as an employer portal admin and runs onboarding, KYB, banking, and plan setup in the Prescience employer portal; track progress via GET /groups/{groupId}/enrollments/{enrollmentId} or webhooks. embedded: onboarding rendered in your own UI when enabled for the integration.
hosted, embedded Response
Enrollment created. The group status moves to enrolled.
"enr_3f7a92c81b40"
"grp_8c2f41d09a3e"
test, live active once Prescience flips the company to prod.
onboarding, active "qt_5b9e2c7f10ad"
"2026-09-01"
"acme.com"
sandbox, prod How post-enrollment onboarding runs. Stamped at creation; defaults to hosted.
hosted, embedded Recomputed from the live onboarding checklist on every read.
Show child attributes
Show child attributes
Provisioning summary for the signatory's employer portal account. Present whenever the signatory was provisioned as an employer portal admin (always on the hosted pathway).
Show child attributes
Show child attributes