> ## Documentation Index
> Fetch the complete documentation index at: https://getprescience.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Account data

> Read aggregate employer account data and enrollment roster data.

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.

<Note>
  **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](/resources/compliance).
</Note>

Both endpoints return `404 not_found` until the group is enrolled. Pre-enrollment, use [`GET /census`](/guides/census#reading-the-census-back) for roster display.

## The account payload, in force

Acme Inc, two months after their 2026-09-01 start, activated to `prod`:

```json theme={null}
{
  "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 element                    | Field(s)                                              | Display guidance                                                                                                                             |
| ----------------------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Tab header / plan badge       | `plan.name`, `company.state`                          | "Prescience Diamond". Show an "Onboarding" badge while `state` is `sandbox`.                                                                 |
| Plan dates                    | `company.startDate`, `company.renewalDate`            | "Plan year Sep 1, 2026 – Sep 1, 2027".                                                                                                       |
| Covered population            | `population.*`                                        | "19 covered lives: 12 employees + 7 dependents".                                                                                             |
| **Funding balance**           | `funding.fundBalanceCents`                            | Headline number: "\$9,901.44 in plan fund". Sub-label months-on-hand: balance ÷ `monthlyFundingCents` → "≈1.5 months".                       |
| **Upcoming pulls**            | `funding.upcomingPulls[]`                             | "Next pull: \$6,600.96 on Dec 1" with `status` chip (`scheduled` / `completed`). `recentPulls` is the history table.                         |
| **Monthly cost**              | `premiums.monthlyPremiumEquivalentCents`, `pepmCents` | "\$6,600.96/month · \$550.08 per employee".                                                                                                  |
| Employee premium contribution | `premiums.employeeContributionCents`                  | Integer cents.                                                                                                                               |
| Premium breakdown             | `premiums.breakdown[]`                                | Label/value rows or a chart. Preserve zero-value rows if your UI shows the full breakdown.                                                   |
| Spend summary                 | `spend.mtdCents`, `spend.ytdCents`                    | "Claims spend: \$234.18 this month · \$8,023.40 plan-year-to-date".                                                                          |
| Spend by category             | `spend.categories[]`                                  | Bar list with `pct`. Sorted by size already.                                                                                                 |
| **Suppressed state**          | `spend.suppressed`, `spend.suppressionNote`           | See below; this state must be designed, not ignored.                                                                                         |
| **Savings**                   | `savings.*`                                           | `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:

```json theme={null}
{
  "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:

```json theme={null}
{
  "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.)

| Column       | Field                                             | Notes                                                                                            |
| ------------ | ------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| Name / email | `firstName`, `lastName`, `email`                  | Join to your employee record via `externalId`.                                                   |
| Status       | `status`                                          | `active` / `terminated` / `cobra`; show COBRA with `cobra.until` ("COBRA through May 31, 2028"). |
| Dependents   | `dependents`                                      | A count, deliberately; no dependent details post-enrollment.                                     |
| App status   | `enrollment.invited`, `enrollment.accountCreated` | The 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](/resources/rate-limits).
