curl --request POST \
--url https://www.getprescience.com/api/partner/v1/groups/{groupId}/elections \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"elections": [
{
"externalId": "emp_1",
"election": "enrolled",
"tier": "employeeSpouse",
"dependents": [
{
"relationship": "spouse"
}
],
"effectiveDate": "2026-11-01"
},
{
"externalId": "emp_2",
"election": "waived",
"waiverReason": "other_employer_group"
}
]
}
'import requests
url = "https://www.getprescience.com/api/partner/v1/groups/{groupId}/elections"
payload = { "elections": [
{
"externalId": "emp_1",
"election": "enrolled",
"tier": "employeeSpouse",
"dependents": [{ "relationship": "spouse" }],
"effectiveDate": "2026-11-01"
},
{
"externalId": "emp_2",
"election": "waived",
"waiverReason": "other_employer_group"
}
] }
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({
elections: [
{
externalId: 'emp_1',
election: 'enrolled',
tier: 'employeeSpouse',
dependents: [{relationship: 'spouse'}],
effectiveDate: '2026-11-01'
},
{externalId: 'emp_2', election: 'waived', waiverReason: 'other_employer_group'}
]
})
};
fetch('https://www.getprescience.com/api/partner/v1/groups/{groupId}/elections', 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}/elections",
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([
'elections' => [
[
'externalId' => 'emp_1',
'election' => 'enrolled',
'tier' => 'employeeSpouse',
'dependents' => [
[
'relationship' => 'spouse'
]
],
'effectiveDate' => '2026-11-01'
],
[
'externalId' => 'emp_2',
'election' => 'waived',
'waiverReason' => 'other_employer_group'
]
]
]),
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}/elections"
payload := strings.NewReader("{\n \"elections\": [\n {\n \"externalId\": \"emp_1\",\n \"election\": \"enrolled\",\n \"tier\": \"employeeSpouse\",\n \"dependents\": [\n {\n \"relationship\": \"spouse\"\n }\n ],\n \"effectiveDate\": \"2026-11-01\"\n },\n {\n \"externalId\": \"emp_2\",\n \"election\": \"waived\",\n \"waiverReason\": \"other_employer_group\"\n }\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}/elections")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"elections\": [\n {\n \"externalId\": \"emp_1\",\n \"election\": \"enrolled\",\n \"tier\": \"employeeSpouse\",\n \"dependents\": [\n {\n \"relationship\": \"spouse\"\n }\n ],\n \"effectiveDate\": \"2026-11-01\"\n },\n {\n \"externalId\": \"emp_2\",\n \"election\": \"waived\",\n \"waiverReason\": \"other_employer_group\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.getprescience.com/api/partner/v1/groups/{groupId}/elections")
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 \"elections\": [\n {\n \"externalId\": \"emp_1\",\n \"election\": \"enrolled\",\n \"tier\": \"employeeSpouse\",\n \"dependents\": [\n {\n \"relationship\": \"spouse\"\n }\n ],\n \"effectiveDate\": \"2026-11-01\"\n },\n {\n \"externalId\": \"emp_2\",\n \"election\": \"waived\",\n \"waiverReason\": \"other_employer_group\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"groupId": "grp_8c2f41d09a3e",
"received": 2,
"accepted": 2,
"enrolled": 1,
"waived": 1,
"invited": 0,
"invitesSuppressed": "test-mode",
"deductionsWebhook": true,
"errors": []
}{
"error": "invalid_request",
"message": "No election passed validation.",
"details": [
{
"field": "elections[0].effectiveDate",
"message": "effectiveDate is required for an enrolled election.",
"index": 0
}
]
}{
"error": "unauthorized",
"message": "Provide a valid partner API key as `Authorization: Bearer psk_...`."
}{
"error": "live_mode_disabled",
"message": "Live mode is not enabled for this account yet. Complete the go-live checklist to enable live keys."
}{
"error": "not_found",
"message": "No group grp_8c2f41d09a3e found."
}{
"error": "conflict",
"message": "Create the group's enrollment before submitting elections."
}{
"error": "rate_limited",
"message": "Too many requests. Please retry later."
}{
"error": "server_error",
"message": "Internal error. The request was not applied."
}Submit elections
For partners that run benefits administration (benefitsAdmin: partner). Sends each employee’s final election. The group needs its enrollment first (409 conflict otherwise). Valid rows are applied and invalid rows come back in errors by index; the response is 400 when no row is valid. Prescience marks the elections on the group’s census, records each coverage effective date, and emails each enrolled member a login (not in test mode). For a partner that runs benefits administration, a deductions.changed webhook follows with each submitted member’s coverage and deduction. Needs the elections capability, which broker keys have by default; other keys return 403 forbidden. Rate limit: 20 writes per minute, shared with census writes.
curl --request POST \
--url https://www.getprescience.com/api/partner/v1/groups/{groupId}/elections \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"elections": [
{
"externalId": "emp_1",
"election": "enrolled",
"tier": "employeeSpouse",
"dependents": [
{
"relationship": "spouse"
}
],
"effectiveDate": "2026-11-01"
},
{
"externalId": "emp_2",
"election": "waived",
"waiverReason": "other_employer_group"
}
]
}
'import requests
url = "https://www.getprescience.com/api/partner/v1/groups/{groupId}/elections"
payload = { "elections": [
{
"externalId": "emp_1",
"election": "enrolled",
"tier": "employeeSpouse",
"dependents": [{ "relationship": "spouse" }],
"effectiveDate": "2026-11-01"
},
{
"externalId": "emp_2",
"election": "waived",
"waiverReason": "other_employer_group"
}
] }
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({
elections: [
{
externalId: 'emp_1',
election: 'enrolled',
tier: 'employeeSpouse',
dependents: [{relationship: 'spouse'}],
effectiveDate: '2026-11-01'
},
{externalId: 'emp_2', election: 'waived', waiverReason: 'other_employer_group'}
]
})
};
fetch('https://www.getprescience.com/api/partner/v1/groups/{groupId}/elections', 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}/elections",
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([
'elections' => [
[
'externalId' => 'emp_1',
'election' => 'enrolled',
'tier' => 'employeeSpouse',
'dependents' => [
[
'relationship' => 'spouse'
]
],
'effectiveDate' => '2026-11-01'
],
[
'externalId' => 'emp_2',
'election' => 'waived',
'waiverReason' => 'other_employer_group'
]
]
]),
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}/elections"
payload := strings.NewReader("{\n \"elections\": [\n {\n \"externalId\": \"emp_1\",\n \"election\": \"enrolled\",\n \"tier\": \"employeeSpouse\",\n \"dependents\": [\n {\n \"relationship\": \"spouse\"\n }\n ],\n \"effectiveDate\": \"2026-11-01\"\n },\n {\n \"externalId\": \"emp_2\",\n \"election\": \"waived\",\n \"waiverReason\": \"other_employer_group\"\n }\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}/elections")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"elections\": [\n {\n \"externalId\": \"emp_1\",\n \"election\": \"enrolled\",\n \"tier\": \"employeeSpouse\",\n \"dependents\": [\n {\n \"relationship\": \"spouse\"\n }\n ],\n \"effectiveDate\": \"2026-11-01\"\n },\n {\n \"externalId\": \"emp_2\",\n \"election\": \"waived\",\n \"waiverReason\": \"other_employer_group\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.getprescience.com/api/partner/v1/groups/{groupId}/elections")
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 \"elections\": [\n {\n \"externalId\": \"emp_1\",\n \"election\": \"enrolled\",\n \"tier\": \"employeeSpouse\",\n \"dependents\": [\n {\n \"relationship\": \"spouse\"\n }\n ],\n \"effectiveDate\": \"2026-11-01\"\n },\n {\n \"externalId\": \"emp_2\",\n \"election\": \"waived\",\n \"waiverReason\": \"other_employer_group\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"groupId": "grp_8c2f41d09a3e",
"received": 2,
"accepted": 2,
"enrolled": 1,
"waived": 1,
"invited": 0,
"invitesSuppressed": "test-mode",
"deductionsWebhook": true,
"errors": []
}{
"error": "invalid_request",
"message": "No election passed validation.",
"details": [
{
"field": "elections[0].effectiveDate",
"message": "effectiveDate is required for an enrolled election.",
"index": 0
}
]
}{
"error": "unauthorized",
"message": "Provide a valid partner API key as `Authorization: Bearer psk_...`."
}{
"error": "live_mode_disabled",
"message": "Live mode is not enabled for this account yet. Complete the go-live checklist to enable live keys."
}{
"error": "not_found",
"message": "No group grp_8c2f41d09a3e found."
}{
"error": "conflict",
"message": "Create the group's enrollment before submitting elections."
}{
"error": "rate_limited",
"message": "Too many requests. Please retry later."
}{
"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. Store them in your secrets manager on issue. Live keys are shown once; the scoped partner portal can show an active sandbox key again.
Headers
Any non-empty string; deterministic keys from your own IDs work best. Repeating the same key with the same body on the same endpoint and mode within 24 hours returns the stored successful response (with Idempotent-Replay: true) instead of re-executing. Error responses are not stored.
Path Parameters
Group ID, e.g. grp_8c2f41d09a3e.
^grp_[0-9a-f]{12}$Body
1 - 10000 elementsShow child attributes
Show child attributes
Response
Elections processed.
Member login emails sent. None are sent in test mode.
test-mode, null Whether a deductions.changed event was sent.
Show child attributes
Show child attributes