Skip to main content
Once a group is enrolled, two read-only endpoints return employer account and roster data:
  • GET /groups/{groupId}/account: funding, premium-equivalent totals, spend, and savings.
  • GET /groups/{groupId}/members: the enrollment roster of who’s invited, active, and on COBRA.
Aggregate and de-identified by design. The account payload never contains named claims, diagnoses, or any individual’s health data, and spend categories are suppressed (k-anonymity) when a category could be traced to a small number of members. You can’t accidentally render PHI, because the API never returns it. See Compliance.
Both endpoints return 404 not_found until the group is enrolled. Pre-enrollment, use GET /census for roster display.

The account payload, in force

Acme Inc, two months after their 2026-09-01 start, activated to prod:
{
  "groupId": "grp_8c2f41d09a3e",
  "asOf": "2026-11-03T16:20:00Z",
  "company": { "displayName": "Acme Inc", "state": "prod", "startDate": "2026-09-01", "renewalDate": "2027-09-01" },
  "plan": {
    "name": "Prescience Diamond",
    "deductibleIndividualCents": 150000,
    "deductibleFamilyCents": 300000,
    "oopMaxIndividualCents": 705000,
    "oopMaxFamilyCents": 1410000,
    "employeePremiumCents": 0
  },
  "population": { "coveredLives": 19, "enrolledEmployees": 12, "dependents": 7 },
  "funding": {
    "fundBalanceCents": 990144,
    "monthlyFundingCents": 660096,
    "upcomingPulls": [ { "date": "2026-12-01", "amountCents": 660096, "status": "scheduled" } ],
    "recentPulls": [
      { "date": "2026-11-01", "amountCents": 660096, "status": "completed" },
      { "date": "2026-10-01", "amountCents": 660096, "status": "completed" }
    ]
  },
  "premiums": {
    "monthlyPremiumEquivalentCents": 660096,
    "pepmCents": 55008,
    "employeeContributionCents": 0,
    "breakdown": [
      { "label": "Claims paid", "cents": 408540 },
      { "label": "HSA funding", "cents": 132019 },
      { "label": "Risk protection & reserves", "cents": 119537 },
      { "label": "Admin fees", "cents": 0 }
    ]
  },
  "spend": {
    "mtdCents": 23418,
    "ytdCents": 802340,
    "categories": [
      { "category": "Prescriptions", "cents": 240702, "pct": 30 },
      { "category": "Specialty care", "cents": 192562, "pct": 24 },
      { "category": "Primary care", "cents": 168491, "pct": 21 },
      { "category": "Imaging & labs", "cents": 120351, "pct": 15 },
      { "category": "Behavioral health", "cents": 80234, "pct": 10 }
    ],
    "suppressed": false
  },
  "savings": { "baselineAnnualCents": 11520000, "savingsYtdCents": 599808 }
}
Note the internal consistency you can assert on: funding.monthlyFundingCents equals premiums.monthlyPremiumEquivalentCents, the breakdown sums to it exactly, and savings.savingsYtdCents is derived from the active baseline comparison.

Field-by-field UI mapping

UI elementField(s)Display guidance
Tab header / plan badgeplan.name, company.state”Prescience Diamond”. Show an “Onboarding” badge while state is sandbox.
Plan datescompany.startDate, company.renewalDate”Plan year Sep 1, 2026 – Sep 1, 2027”.
Covered populationpopulation.*”19 covered lives: 12 employees + 7 dependents”.
Funding balancefunding.fundBalanceCentsHeadline number: “$9,901.44 in plan fund”. Sub-label months-on-hand: balance ÷ monthlyFundingCents → “≈1.5 months”.
Upcoming pullsfunding.upcomingPulls[]”Next pull: $6,600.96 on Dec 1” with status chip (scheduled / completed). recentPulls is the history table.
Monthly costpremiums.monthlyPremiumEquivalentCents, pepmCents”$6,600.96/month · $550.08 per employee”.
Employee premium contributionpremiums.employeeContributionCentsInteger cents.
Premium breakdownpremiums.breakdown[]Label/value rows or a chart. Preserve zero-value rows if your UI shows the full breakdown.
Spend summaryspend.mtdCents, spend.ytdCents”Claims spend: $234.18 this month · $8,023.40 plan-year-to-date”.
Spend by categoryspend.categories[]Bar list with pct. Sorted by size already.
Suppressed statespend.suppressed, spend.suppressionNoteSee below; this state must be designed, not ignored.
Savingssavings.*baselineAnnualCents is prior-plan cost projected over the plan year; savingsYtdCents is current plan-year savings against that baseline.
All money is integer cents. Format with your standard currency utility, never floats.

The suppressed-spend case

For small groups (or early plan years), category-level spend could let an employer guess at an individual’s care. When the k-anonymity check trips, the API withholds categories rather than thin them:
{
  "spend": {
    "mtdCents": 23418,
    "ytdCents": 802340,
    "categories": [],
    "suppressed": true,
    "suppressionNote": "Spend categories are hidden for small groups to protect member privacy."
  }
}
Render the totals (always safe), replace the category chart with the suppressionNote, and treat it as a normal state, not an error or an empty-data bug. Categories reappear automatically once the population supports them.

The roster

GET /groups/{groupId}/members powers the people table, with enrollment-admin data only:
{
  "members": [
    { "memberId": "mem_c4a91f27e83d", "externalId": "emp_0001", "firstName": "Jordan", "lastName": "Reyes",
      "email": "jordan@acme.com", "status": "active", "employmentType": "full_time", "hireDate": "2024-03-01",
      "dependents": 0, "enrollment": { "invited": true, "accountCreated": true } },
    { "memberId": "mem_f7b3d59e02a4", "externalId": "emp_0008", "firstName": "Grace", "lastName": "Okafor",
      "email": "grace@acme.com", "status": "active", "employmentType": "full_time", "hireDate": "2023-07-15",
      "dependents": 1, "enrollment": { "invited": true, "accountCreated": false } },
    { "memberId": "mem_92e4b7a1d0c6", "externalId": "emp_0009", "firstName": "Tom", "lastName": "Becker",
      "email": "tom@acme.com", "status": "cobra", "employmentType": "full_time", "hireDate": "2022-01-10",
      "dependents": 1, "enrollment": { "invited": true, "accountCreated": true }, "cobra": { "until": "2028-05-31" } }
  ],
  "count": 12
}
(Array truncated here; the API returns all members.)
ColumnFieldNotes
Name / emailfirstName, lastName, emailJoin to your employee record via externalId.
Statusstatusactive / terminated / cobra; show COBRA with cobra.until (“COBRA through May 31, 2028”).
DependentsdependentsA count, deliberately; no dependent details post-enrollment.
App statusenrollment.invited, enrollment.accountCreatedThe useful HR nudge: invited-but-no-account members are who to ping during open enrollment.
dependents is a count and enrollment is two booleans on purpose: the roster tells the employer who is covered and onboarded, never anything about anyone’s health.

Freshness

asOf timestamps every account read. The data behind it updates as pulls settle and claims process. Cache for minutes, not days; on-load fetching with a short server-side cache is the pattern our own portal uses. Both endpoints fall under the standard 120 req/min rate limit.