Pay statements

Read an employee's pay statement, preview gross-to-net before a run closes, and cancel a statement in a draft run with the Wingspan V3 API.

A pay statement is one employee's pay for one payroll run: their earnings, what was withheld, and their net pay. Wingspan creates it when you approve the employee's work log, and pays it with the run. This page shows you what a pay statement contains, how to preview one before the run closes, and how to cancel one.

What a pay statement is

Read a pay statement with GET /v3/payments/pay-statements/{payStatementId}. This one is for a week with 8 regular hours at $20 and 2 overtime hours at $30, for an employee at a California worksite who's on the default withholding elections.

// 200 OK (trimmed)
{
  "id": "GUAJztqobp9aoa1fCRJ92f",
  "payStatementNumber": "K4TQZ-001-PS",
  "status": "Draft",
  "payrollRunId": "TVDpIcgEQZ0E64NXJeC2Ps",
  "payPeriodId": "ha2GMh5tQiSpEyCNFbzd5D",
  "payeeAccountId": "IJoFzShicUxKFl03UuRGSd",
  "payerAccountId": "23Gvh0YtpH6bNj4iOxLqET",
  "payPeriodStartDate": "2026-11-06T12:00:00.000Z",
  "payPeriodEndDate": "2026-11-12T12:00:00.000Z",
  "payDate": "2026-11-13T12:00:00.000Z",
  "payPeriodsPerYear": 52,
  "earnings": [
    { "type": "Regular", "workLogId": "mvG1MkSioJyHDrW5vRGlMf", "hours": 8, "amount": 160, "payerPayeeEngagementId": "j88P41LYjxNCLZ6CmGNHqH" },
    { "type": "Overtime", "workLogId": "mvG1MkSioJyHDrW5vRGlMf", "hours": 2, "amount": 60, "payerPayeeEngagementId": "j88P41LYjxNCLZ6CmGNHqH" }
  ],
  "payeeTaxes": [
    { "description": "Federal Social Security (Employee)", "amount": 13.64, "taxCodeId": "OhbVrpoiVgRV5IfLBcbfno" },
    { "description": "Federal Income Tax", "amount": 0, "taxCodeId": "GMbJmTPSIAoCLrZ3aWZkSB" },
    { "description": "Federal Medicare (Employee)", "amount": 3.19, "taxCodeId": "vrjn9Wvgfygw2wMqZcUDIh" },
    { "description": "Federal Additional Medicare (Employee)", "amount": 0, "taxCodeId": "7yfJs1ON43xKmTecQoXsf2" },
    { "description": "California State Tax", "amount": 0, "taxCodeId": "o3gyrDO1xkxwnQrS7RPeMO" },
    { "description": "California SDI (Employee)", "amount": 2.86, "taxCodeId": "Tq7mVb2XcN4kLp9RwZs3Hd" }
  ],
  "payerTaxes": [
    { "description": "Federal Social Security (Employer)", "amount": 13.64, "taxCodeId": "kIUpkDyr7OSJoRu1XXdo0c" },
    { "description": "Federal Unemployment (FUTA)", "amount": 1.32, "taxCodeId": "Zuzren68K4TunPFz46PDjq" },
    { "description": "Federal Medicare (Employer)", "amount": 3.19, "taxCodeId": "ipVJIqVLB5LzxoiGFfWd3h" },
    { "description": "California State Unemployment Tax", "amount": 7.48, "taxCodeId": "jOkYRBMeyyMDHqJ38aRUhR" },
    { "description": "California Employment Training Tax", "amount": 0.22, "taxCodeId": "Bv5nQw8RtY2mKc6LxPz4Jf" }
  ],
  "amountDetails": {
    "grossPay": 220,
    "taxWithheld": 19.69,
    "netPay": 200.31,
    "grossLiabilityAmount": 245.85,
    "ytd": { "grossPay": 220, "taxWithheld": 19.69, "netPay": 200.31 },
    "qtd": { "grossPay": 220, "taxWithheld": 19.69, "netPay": 200.31 },
    "mtd": { "grossPay": 220, "taxWithheld": 19.69, "netPay": 200.31 }
  }
}

A week this small is under the federal standard deduction and California's low-income exemption, so both income tax lines are 0.

FieldWhat it means
statusDraft until the run is paid, then Paid. Failed if Wingspan couldn't process it.
earningsOne line per wage type per work log, with the hours and the amount.
payeeTaxesWhat was withheld from the employee's pay. Each entry has a taxCodeId, a description, and an amount.
payerTaxesYour employer taxes on this pay. Only you see these.
amountDetails.grossPayTotal earnings before withholding.
amountDetails.taxWithheldTotal withheld from the employee.
amountDetails.netPayWhat the employee takes home.
amountDetails.grossLiabilityAmountWhat this statement costs you: gross pay plus your employer taxes. Only you see this.
amountDetails.ytd, qtd, mtdYear-, quarter-, and month-to-date totals, including this statement.
events.paidAt, events.depositedAtWhen the employee's deposit was sent, and when it settled. Present once the run is paid.

Wage types

typeUse it for
RegularRegular hours.
OvertimeOvertime hours, at the overtime rate.
BonusA bonus.
CommissionA commission.
ReimbursementA reimbursed expense, such as mileage.

The wage type decides how each earning line is taxed.

Preview gross-to-net

Before a run closes, see what an employee will take home, and what they'll cost you, with POST /v3/payments/pay-statements/preview. It models every unpaid work log the employee has in the pay period, including ones you haven't approved yet. The preview doesn't save anything.

curl -X POST https://api.wingspan.app/v3/payments/pay-statements/preview \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "payPeriodId": "ha2GMh5tQiSpEyCNFbzd5D",
    "payeeAccountId": "IJoFzShicUxKFl03UuRGSd"
  }'
// 200 OK (trimmed)
{
  "payeeTaxes": [
    { "description": "Federal Social Security (Employee)", "amount": 13.64, "taxCodeId": "OhbVrpoiVgRV5IfLBcbfno" },
    { "description": "Federal Income Tax", "amount": 0, "taxCodeId": "GMbJmTPSIAoCLrZ3aWZkSB" },
    { "description": "Federal Medicare (Employee)", "amount": 3.19, "taxCodeId": "vrjn9Wvgfygw2wMqZcUDIh" },
    { "description": "California State Tax", "amount": 0, "taxCodeId": "o3gyrDO1xkxwnQrS7RPeMO" },
    { "description": "California SDI (Employee)", "amount": 2.86, "taxCodeId": "Tq7mVb2XcN4kLp9RwZs3Hd" }
  ],
  "payerTaxes": [
    { "description": "Federal Social Security (Employer)", "amount": 13.64, "taxCodeId": "kIUpkDyr7OSJoRu1XXdo0c" },
    { "description": "Federal Unemployment (FUTA)", "amount": 1.32, "taxCodeId": "Zuzren68K4TunPFz46PDjq" },
    { "description": "Federal Medicare (Employer)", "amount": 3.19, "taxCodeId": "ipVJIqVLB5LzxoiGFfWd3h" },
    { "description": "California State Unemployment Tax", "amount": 7.48, "taxCodeId": "jOkYRBMeyyMDHqJ38aRUhR" },
    { "description": "California Employment Training Tax", "amount": 0.22, "taxCodeId": "Bv5nQw8RtY2mKc6LxPz4Jf" }
  ],
  "amountDetails": {
    "grossPay": 220,
    "taxWithheld": 19.69,
    "netPay": 200.31,
    "grossLiabilityAmount": 245.85
  },
  "payDate": "2026-11-13T12:00:00.000Z",
  "payPeriodsPerYear": 52,
  "workLogIds": ["mvG1MkSioJyHDrW5vRGlMf"]
}

To preview only some work logs, send their IDs in workLogIds. Each one has to be an unpaid work log for that employee and pay period.

Read the pay statements in a run

List pay statements with GET /v3/payments/pay-statements. Filter by run, pay period, employee, or status.

curl -G https://api.wingspan.app/v3/payments/pay-statements \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  --data-urlencode "filter[payrollRunId][eq]=TVDpIcgEQZ0E64NXJeC2Ps"
FilterReturns
filter[payrollRunId][eq]Pay statements in one run.
filter[payPeriodId][eq]Pay statements for one pay period.
filter[payeeAccountId][eq]One employee's pay statements.
filter[status][anyOf][]Pay statements in any of these statuses.
filter[payDate][gte], [lte]Pay statements paid in a date range.

What the employee sees

An employee sees their own pay statements once they're Paid, in Wingspan or in your app, and can read them with the same endpoints using their own credentials. They don't see your employer taxes or grossLiabilityAmount.

Cancel a pay statement

To take an employee out of a run, cancel their pay statement with POST /v3/payments/pay-statements/{payStatementId}/cancel. You can cancel while the statement and its run are both Draft. Cancelling removes the statement from the run, moves its work logs back to InReview, and recalculates the run's totalAmount. The response is the statement as it was when you cancelled it. Fix the hours and approve the work logs again to create a new statement, or reject them with a reason if they shouldn't be paid.

curl -X POST https://api.wingspan.app/v3/payments/pay-statements/GUAJztqobp9aoa1fCRJ92f/cancel \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

What can go wrong

Status and codeCauseFix
404 reading a pay statementThe caller isn't the employer or the employee, or an employee is reading a statement that isn't Paid yet.Read it as the employer, or wait until the run is paid.
409 on cancelThe statement is Paid or Failed, or its run is past Draft.Cancel only in a draft run.
400 on preview with workLogIdsA listed work log isn't an unpaid work log for that employee and pay period.Send only that employee's unpaid work logs for the period, or leave workLogIds out.

Related pages


Did this page help you?