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

# Payroll results

> Report each completed payroll's actual HSA withholding so Prescience deposits exactly that.

When your payroll withholds an employee's HSA contribution, Prescience moves that money into the employee's HSA. Prescience deposits only what you report as actually withheld, so after every completed payroll, post its results:

```http theme={null}
POST /v1/groups/{groupId}/payroll-results
```

The group must be enrolled. Nothing on this endpoint moves money by itself: results become payroll evidence, and deposits follow Prescience's own checks and approvals.

## One completed payroll

```json theme={null}
{
  "eventId": "evt_2026_10_30_regular",
  "version": 1,
  "companyId": "4c1f0e5a-9b1d-4a51-8f5e-2d7a3c9e61b0",
  "payrollRunId": "pay_8f2c1d",
  "contributionYear": 2026,
  "payday": "2026-10-30",
  "type": "regular",
  "status": "paid",
  "isVoid": false,
  "sourceReference": "check:payroll:pay_8f2c1d",
  "sourceTimestamp": "2026-10-30T18:00:00Z",
  "rosterComplete": true,
  "employees": [
    {
      "employeeId": "emp_7h3k",
      "email": "sam@northstarlabs.com",
      "employmentStatus": "active",
      "payrollItemId": "itm_5d2e",
      "itemStatus": "paid",
      "hsaWithheldCents": 12500,
      "expectedHsaCents": 12500,
      "deductionId": "ben_hsa_7h3k"
    },
    {
      "employeeId": "emp_2p9q",
      "email": "lee@northstarlabs.com",
      "employmentStatus": "active",
      "payrollItemId": "itm_9a4c",
      "itemStatus": "paid",
      "hsaWithheldCents": 0,
      "expectedHsaCents": 0,
      "deductionId": "ben_hsa_2p9q"
    }
  ]
}
```

| Field                                     | Meaning                                                                                                                                                                                                                                                                                                                                |
| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `eventId`, `version`                      | Your stable ID for this report. Send a correction as the same `eventId` with a higher `version`.                                                                                                                                                                                                                                       |
| `companyId`                               | Your company ID, the group's `externalId`.                                                                                                                                                                                                                                                                                             |
| `employees[].employeeId`                  | The employee's ID in your payroll (Check `Employee.id`), the same `externalId` you sent in the census. Prescience finds the employee by this ID, not by email. An ID that isn't in the census is `needs_review` when the email belongs to a member with no ID on file, and `rejected` when it belongs to a member with a different ID. |
| `payrollRunId`                            | Your stable payroll run ID.                                                                                                                                                                                                                                                                                                            |
| `contributionYear`                        | The tax year the withholding counts toward. Must be the payday's year.                                                                                                                                                                                                                                                                 |
| `payday`                                  | The payroll's check date.                                                                                                                                                                                                                                                                                                              |
| `type`                                    | Check `payroll.type`: `regular`, `off_cycle`, `amendment`, `balancing` or `third_party_sick_pay`. Amendments and balancing payrolls are treated as corrections.                                                                                                                                                                        |
| `status`                                  | Check `payroll.status`. Send it once the payroll is `paid` or `partially_paid` (then each item's status decides). `failed` is final too.                                                                                                                                                                                               |
| `isVoid`                                  | Check `payroll.is_void`. A void payroll is recorded as its own reversal: send it once paid, with negative amounts.                                                                                                                                                                                                                     |
| `sourceReference`, `sourceTimestamp`      | Where and when this came from in your system.                                                                                                                                                                                                                                                                                          |
| `rosterComplete`                          | `true` only when `employees` lists every employee with a Prescience HSA deduction on this payroll, including zeros.                                                                                                                                                                                                                    |
| `employees[].payrollItemId`, `itemStatus` | The employee's own payroll item and its status (Check `payroll_item.id` and `status`). A `paid` or `partially_paid` item on a completed payroll counts as withheld (a partially paid item still had its deductions taken).                                                                                                             |
| `employees[].voidOf`                      | The payroll item this one voids (Check `void_of`), for a reversal. Its amount is negative.                                                                                                                                                                                                                                             |
| `employees[].hsaWithheldCents`            | Actual pre-tax HSA withholding, in integer cents (Check's `employee_amount` for the employee's `hsa` benefit is a dollar string: convert it). `0` means you confirmed nothing was withheld. `null` means you don't know yet. Negative only on a completed correction or void. A `failed` item is `0` or `null`.                        |
| `employees[].expectedHsaCents`            | What you meant to withhold on this paycheck, if different from actual.                                                                                                                                                                                                                                                                 |
| `employees[].deductionId`                 | Your ID for the employee's HSA benefit or deduction.                                                                                                                                                                                                                                                                                   |

## Responses

* **`202`** with the stored event, and what happened to each employee (`employees[].outcome`):
  * `recorded`: accepted as payroll evidence. `needs_review`: accepted, and Prescience's team reviews it.
  * `payday_in_future`, `busy`, `not_tracked`: kept and retried automatically when you post your next payroll.
  * `not_on_roster`: the email isn't one of this employer's employees on Prescience.
  * `rejected`: the facts didn't pass validation; Prescience's team reviews it.
  * `validated`: sandbox only. The report was checked, and nothing was recorded.
* **`200`** with the same body when you send the same `eventId` and `version` again. Retrying is always safe.
* **`409 conflict`** when an `eventId` and `version` you already sent arrives with different content. Send it as a new `version`.
* **`400` / `422`** when fields are missing or inconsistent, for example a `companyId` that isn't this group's.

## What is held

These are stored with `status: "held"` and are never used as payroll evidence: a payroll that is still `draft`, `pending` or `processing`, `rosterComplete: false`, or no `employees`. Post the results once the payroll is paid.

## Sandbox

With a `psk_test_` key the same checks run, and every employee comes back `validated`. Nothing is recorded and no money is involved.
