curl --request POST \
--url https://www.getprescience.com/api/partner/v1/groups/{groupId}/quotes \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{}'import requests
url = "https://www.getprescience.com/api/partner/v1/groups/{groupId}/quotes"
payload = {}
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({})
};
fetch('https://www.getprescience.com/api/partner/v1/groups/{groupId}/quotes', 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}/quotes",
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([
]),
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}/quotes"
payload := strings.NewReader("{}")
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}/quotes")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.getprescience.com/api/partner/v1/groups/{groupId}/quotes")
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 = "{}"
response = http.request(request)
puts response.read_body{
"id": "qt_5b9e2c7f10ad",
"groupId": "grp_8c2f41d09a3e",
"mode": "test",
"status": "ready",
"pricingBasis": "market_rates",
"plan": {
"id": "diamond",
"name": "Prescience Diamond"
},
"planYearStartDate": "2026-09-01",
"expiresAt": "2026-07-10T17:22:05Z",
"census": {
"employees": 12,
"coveredLives": 19,
"tiers": {
"employeeOnly": 7,
"employeeSpouse": 2,
"employeeChildren": 1,
"family": 2
}
},
"monthly": {
"totalCents": 660096,
"pepmCents": 55008,
"byTier": {
"employeeOnly": {
"count": 7,
"avgCents": 34047
},
"employeeSpouse": {
"count": 2,
"avgCents": 89166
},
"employeeChildren": {
"count": 1,
"avgCents": 53987
},
"family": {
"count": 2,
"avgCents": 94724
}
}
},
"annual": {
"totalCents": 7921152
},
"employeeContribution": {
"premiumCents": 0
},
"comparison": {
"priorPepmCents": 0,
"savingsMonthlyCents": 299904,
"savingsAnnualCents": 3598848,
"savingsPct": 31
},
"fundingBreakdown": {
"expectedClaimsPct": 78,
"stopLossPct": 12,
"careNavigationPct": 10,
"adminFeesPct": 0,
"note": "Illustrative split of the premium-equivalent."
},
"assumptions": [
"Dependent elections were not supplied, so this preliminary model uses a normalized small-group household mix."
],
"pricing": {
"source": "code_default"
},
"createdAt": "2026-06-10T17:22:05Z"
}{
"error": "invalid_request",
"message": "planYearStartDate must be YYYY-MM-DD.",
"details": [
{
"field": "planYearStartDate",
"message": "planYearStartDate must be YYYY-MM-DD"
}
]
}{
"error": "unauthorized",
"message": "Provide a valid partner API key as `Authorization: Bearer psk_...`."
}{
"error": "not_found",
"message": "No group grp_8c2f41d09a3e found."
}{
"error": "rates_pending",
"message": "Market rates for this group have not landed yet. Rates are fetched automatically when a census is synced; retry once the sweep completes."
}{
"error": "census_required",
"message": "Upload a census with PUT /groups/{groupId}/census before quoting."
}{
"error": "rate_limited",
"message": "Rate limit exceeded. Retry after 12 seconds."
}{
"error": "server_error",
"message": "Internal error. The request was not applied."
}Create a quote
Rates the stored census against the group’s current local market-plan snapshot and returns a complete preliminary quote synchronously once the census-triggered market comparison is ready. Returns 409 rates_pending while that comparison is running. Groups requiring human review return status: in_review and are finalized by underwriting (webhook quote.finalized). Quotes expire per configuration (default 30 days). A new market sweep may change available plans or rates. Rate limit: 60 quote creates per hour.
curl --request POST \
--url https://www.getprescience.com/api/partner/v1/groups/{groupId}/quotes \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{}'import requests
url = "https://www.getprescience.com/api/partner/v1/groups/{groupId}/quotes"
payload = {}
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({})
};
fetch('https://www.getprescience.com/api/partner/v1/groups/{groupId}/quotes', 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}/quotes",
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([
]),
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}/quotes"
payload := strings.NewReader("{}")
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}/quotes")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.getprescience.com/api/partner/v1/groups/{groupId}/quotes")
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 = "{}"
response = http.request(request)
puts response.read_body{
"id": "qt_5b9e2c7f10ad",
"groupId": "grp_8c2f41d09a3e",
"mode": "test",
"status": "ready",
"pricingBasis": "market_rates",
"plan": {
"id": "diamond",
"name": "Prescience Diamond"
},
"planYearStartDate": "2026-09-01",
"expiresAt": "2026-07-10T17:22:05Z",
"census": {
"employees": 12,
"coveredLives": 19,
"tiers": {
"employeeOnly": 7,
"employeeSpouse": 2,
"employeeChildren": 1,
"family": 2
}
},
"monthly": {
"totalCents": 660096,
"pepmCents": 55008,
"byTier": {
"employeeOnly": {
"count": 7,
"avgCents": 34047
},
"employeeSpouse": {
"count": 2,
"avgCents": 89166
},
"employeeChildren": {
"count": 1,
"avgCents": 53987
},
"family": {
"count": 2,
"avgCents": 94724
}
}
},
"annual": {
"totalCents": 7921152
},
"employeeContribution": {
"premiumCents": 0
},
"comparison": {
"priorPepmCents": 0,
"savingsMonthlyCents": 299904,
"savingsAnnualCents": 3598848,
"savingsPct": 31
},
"fundingBreakdown": {
"expectedClaimsPct": 78,
"stopLossPct": 12,
"careNavigationPct": 10,
"adminFeesPct": 0,
"note": "Illustrative split of the premium-equivalent."
},
"assumptions": [
"Dependent elections were not supplied, so this preliminary model uses a normalized small-group household mix."
],
"pricing": {
"source": "code_default"
},
"createdAt": "2026-06-10T17:22:05Z"
}{
"error": "invalid_request",
"message": "planYearStartDate must be YYYY-MM-DD.",
"details": [
{
"field": "planYearStartDate",
"message": "planYearStartDate must be YYYY-MM-DD"
}
]
}{
"error": "unauthorized",
"message": "Provide a valid partner API key as `Authorization: Bearer psk_...`."
}{
"error": "not_found",
"message": "No group grp_8c2f41d09a3e found."
}{
"error": "rates_pending",
"message": "Market rates for this group have not landed yet. Rates are fetched automatically when a census is synced; retry once the sweep completes."
}{
"error": "census_required",
"message": "Upload a census with PUT /groups/{groupId}/census before quoting."
}{
"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
Response
The quote.
"qt_5b9e2c7f10ad"
"grp_8c2f41d09a3e"
test, live ready for most groups (synchronous). Groups above the in-review employee threshold (default 200) return in_review and are finalized by Prescience underwriting; listen for the quote.finalized webhook.
ready, in_review, expired Current quotes use market_rates and are priced from the group's local platinum PPO benchmark and feasible bronze PPO underlying option. Final pricing is confirmed during underwriting and onboarding.
"market_rates"Show child attributes
Show child attributes
"2026-09-01"
Expiry is configuration-driven; the default window is 30 days after creation. Enrolling against an expired quote returns 410 quote_expired.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Pricing metadata: which configuration layer produced this quote. Additive in v1.1; absent on quotes created before it. All other quote fields are unchanged.
Show child attributes
Show child attributes