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 two building block operations, which can be combined freely:
- Void payrolls — Creating a payroll that exactly zero out an existing payroll item or contractor payment, canceling its wages and tax liabilities.
- Add payrolls — Adding new (either managed or external) payrolls with a backdated payday.
These are grouped onto a correction, which represents 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 (3) 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 backdated 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, and new payrolls or void payrolls can be attached to it.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, and must be retried.
Check sends created, updated, and deleted webhooks for Corrections, so you can track lifecycle changes (like preview completion and approval) without polling the API.
Example: voiding and replacing 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 corrected payroll item
Create a replacement payroll attached to the same correction via the correction body parameter. This should be done either using the External Payroll API or the Payroll API, depending on whether the payday of the payroll being added is before or after the company's start date.
- If the payday is before the company's start date: The payroll is external (non-managed), meaning that the tax calculation for the payroll was performed by a prior provider and must be entered on the payroll. Create the payroll using the External Payroll API and the Create an external payroll endpoint.
- If the payday is on or after the company's start date: The payroll is managed by Check, and Check will calculate taxes for the payroll. Create the payroll using the regular Payroll API and the Create a payroll endpoint.
{
"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": ["..."]
}
]
}When creating a managed payroll (with a payday after the company's start date), you will not be able to preview the payroll directly with the Payroll API. Rather, the payroll will be previewed as part of previewing the correction, as shown below.
4. Preview the correction
Once you have added all of the voids and/or backdated payrolls to the correction, the next step is to preview the correction.
POST /corrections/cor_Bw6EkMDmxCPeVQ2eYzLu/preview
Previewing a correction is asynchronous, and does several things:
- It previews any managed payrolls attached to the correction.
- It computes the
totalsof the correction, which indicates the expected money movement for the correction. This includes the amount that will be directly debited from or refunded to the employer (thecash_requirement), and any tax funds that were already remitted and are refundable from the agencyagency_refund). - It rebalances any impacted closed quarters, which get added to the list of operations on the correction as shown below. These new payrolls get 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.
{
...,
"operations": [
{
"operations": "balance_quarter",
"creates": "pay_Vg3RvNwqLpTz8oYaGdQE", // Balancing adjustment from correction
"corrects": "pay_Jd9nWuBqOxSz5eKmCvhT" // Original balancing payroll
},
...
]
}The preview is invalidated if payrolls are added to or removed from the correction.
5. 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 last preview. 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.
Updated 16 days ago

