Correcting Pay History
Processing voids and historical pay adds over the API
PreviewThis guide is a preview of the upcoming Corrections API. These endpoints are not yet available — this guide illustrates what the API will look like, and details may change before release.
Overview
Mistakes happen in payroll. An employee is paid after their termination date, a benefit is set up with the wrong amount, or pay history is imported incorrectly during a company's initial setup.
The Corrections API lets you fix pay history programmatically. It supports three building blocks, which can be combined freely:
- Voids — payrolls that exactly zero out an existing payroll item or contractor payment, canceling its wages and tax liabilities.
- Replacement payrolls — managed payrolls attached to a correction that run through the standard preview and approval flow, but with a past
paydayandpayment_methodmanualon every item. - External payrolls — non-managed payrolls that add pay history, but were not paid out through Check.
All three are grouped onto a correction: a bundle of changes to a company's pay history that is previewed, approved, and fulfilled as a single unit. Because everything on a correction is processed together, Check offsets the resulting tax liabilities against each other — taxes recovered by a void can fund the taxes owed on its replacement, so nothing is double-collected.
This unlocks three common workflows:
- Standalone voids — canceling pay that should never have been processed (e.g., accidentally paying a terminated employee on a payroll).
- Void and replace — void a mistake on a payroll and replace it with corrected pay history, as either a managed replacement payroll or an external payroll.
- Add missing historical payrolls — uploading a payroll that was missed during setup or run manually outside of Check.
The Correction lifecycle
A correction moves through the following states:
draft— the correction is editable. You attach void payrolls, replacement payrolls, and external payrolls to it, and run previews.pending— the correction has been approved. Its money movement is scheduled to process on the correction'ssettlement_date. Apendingcorrection can be reopened until itsreopen_deadlineto make further changes, which returns it todraftand deletes its fulfillment.processing— fulfillment has begun processing, and the correction can no longer be reopened.settled— fulfillment has been processed and the correction is reflected in the company's pay history.failed— the fulfillment could not be processed.
Check sends created, updated, and deleted webhooks for Corrections, so you can track lifecycle changes (like preview completion and approval) without polling the API.
Walkthrough: void and replace a payroll
The example below corrects a payroll item that was processed with the wrong amounts by voiding it and replacing it with corrected values.
1. Create a correction
{
"company": "com_sx3svU6K8c5ZkSFlOh5p",
"year": 2026,
"settlement_date": "2026-07-15",
"description": "Void and replace 3/31 payroll for J. Smith"
}The correction is created in draft. company and year are required — all payrolls attached to the correction must belong to the correction's tax year. The other fields are optional:
settlement_date— the banking day on which any resulting debit or refund will be processed. Must be a valid banking day on or after the earliest date ACH can still reach for settlement. If omitted, a date is chosen when the correction is approved.bank_account— the bank account to debit or credit at fulfillment. If omitted, Check stamps the company's current default bank account.
2. Void the erroneous payroll item
Use Void a payroll to create a void payroll and attach it to the correction. By default all items on the payroll are voided; pass a subset object to void only specific payroll items or contractor payments.
{
"correction": "cor_Bw6EkMDmxCPeVQ2eYzLu",
"subset": {
"payroll_items": ["itm_Ue75kUcWex5JRGTRuqux"]
}
}The response is a draft payroll with is_void: true whose amounts are the exact negation of the original item. Void payrolls are not previewed or approved through the Payroll API — they are processed with the correction.
3. Add the replacement pay history
Create a replacement payroll attached to the same correction via the correction body parameter. Choose the surface that matches how the replacement should run:
- Managed replacement — use Create a payroll when the replacement should preview, approve, and calculate taxes like an ordinary managed payroll. The
paydaymust be in the past, and every nested payroll item and contractor payment must usepayment_methodmanual. - External replacement — use Create an external payroll when the replacement is historical pay that was not paid out through Check.
A common pattern is to start from a replica of the voided item and edit the values that were wrong.
{
"company": "com_sx3svU6K8c5ZkSFlOh5p",
"correction": "cor_Bw6EkMDmxCPeVQ2eYzLu",
"period_start": "2026-03-14",
"period_end": "2026-03-27",
"payday": "2026-03-31",
"items": [
{
"employee": "emp_zGGp6wYcxAeu1Ng8IA7v",
"payment_method": "manual",
"earnings": ["..."]
}
]
}For an external replacement:
{
"company": "com_sx3svU6K8c5ZkSFlOh5p",
"correction": "cor_Bw6EkMDmxCPeVQ2eYzLu",
"period_start": "2026-03-14",
"period_end": "2026-03-27",
"payday": "2026-03-31",
"items": ["..."]
}Use Preview payroll and Update a payroll for managed replacements, or Preview an external payroll and Update an external payroll for external replacements, to have Check calculate taxes on the replacement payroll.
External payrolls after go-liveOnce a company has started running managed payrolls with Check, new external payrolls must be attached to a correction — creation without the
correctionparameter returns a validation error. This replaces the previous behavior, where external payrolls could not be created at all after go-live.
4. Preview the correction
POST /corrections/cor_Bw6EkMDmxCPeVQ2eYzLu/preview
Previewing does two things: it rebalances any impacted closed quarters (see below), and it prices the correction without moving money. The endpoint returns 202 Accepted; monitor progress via the preview object on the correction or the correction updated webhook. Once the preview succeeds, the correction's totals is populated with the money movement that fulfilling the correction would require, using the same shape as fulfillment totals.
The preview is invalidated if payrolls are added to or removed from the correction.
5. Review the effects
Before approving, you can show the employer exactly what will happen:
totalson the correction summarizes the money movement:cash_requirement(debited or refunded by Check),cash_requirement_waived, andagency_refundable(amounts refunded directly by tax agencies).- Get a correction payroll journal returns the standard payroll journal report scoped to just the payrolls on the correction, for reviewing the detailed employee-level effects.
- Get a correction payroll summary returns the standard payroll summary report scoped to the correction, for reviewing the aggregate effects.
6. Approve the correction
POST /corrections/cor_Bw6EkMDmxCPeVQ2eYzLu/approve
Like preview, approving is asynchronous: the endpoint returns 202 Accepted, and Check recalculates the correction's money movement and compares it against the totals you reviewed in step 5. There are a variety of reasons why the required money movement may change between preview and approval, such as tax payments being remitted or additional payrolls outside of the correction being approved.
Monitor the approval via the approval object on the correction, by listening for the correction updated webhook, or by polling Get a correction.
- If the amounts are unchanged, the correction moves to
pending, and its money movement is scheduled to process on thesettlement_date. - If the amounts have changed — for example, because the company's pay history changed after the preview was run — the approval fails with
approval.error_codeset tofulfillment_changed. The correction remains indraft, withtotalsrefreshed to reflect the updated amounts. Review the new totals, re-run Preview a correction if needed, and then approve again.
{
"status": "draft",
"approval": {
"status": "failed",
"started_at": "2026-06-25T12:24:23.441459Z",
"error_code": "fulfillment_changed"
}
}A correction cannot be approved if it has no payrolls attached, or if its preview is stale or has not been run. While an approval is in progress, the correction cannot be edited, deleted, or previewed.
Once the correction is pending, if something needs to change, reopen the correction to return it to draft. Reopening is possible until the correction's reopen_deadline, after which fulfillment begins processing.
Correcting closed quarters
When a correction changes pay history in a closed quarter, previewing the correction will trigger the creation of a balancing payroll in that quarter and every subsequent closed quarter in the tax year. For example, if we are currently in Q4 of a tax year, and a void is created in Q2, then previewing the correction will create a balancing payroll for Q2 and Q3.
The purpose of these balancing payrolls is to ensure that every closed period has a consistent and accurate set of taxes that complies with agency tax rules. When the correction is previewed, the resulting balancing payrolls are attached to the correction with the balancing role:
{
"payrolls": [
{ "payroll": "pay_Mt7cJqXcVfW2yPKhBvsN", "role": "void" },
{ "payroll": "pay_Vg3RvNwqLpTz8oYaGdQE", "role": "new" },
{ "payroll": "pay_Jd9nWuBqOxSz5eKmCvhT", "role": "balancing" }
]
}Balancing payrolls are fulfilled alongside the other payrolls on the correction, in a single transaction. For more on how balancing and fulfillments work generally, see Balancing Payrolls & Fulfillment Receipts.
Updated 9 days ago

