Payroll cycle
Every payroll in the Friday API moves through a series of statuses — from initial draft to final payment. This guide explains each status, what transitions are possible, and how to track the lifecycle through the API and webhooks.
Statuses at a Glance
┌───────────┐
│ draft │◄──────────────────────┐
└─────┬─────┘ │
approve │ delete │ reopen
▼ │
┌───────────┐ ┌─────┴─────┐
│ pending │─────────────────►│ reopened │
└─────┬─────┘ └───────────┘
│
▼
┌───────────┐
│processing │
└─────┬─────┘
╱ ╲
▼ ▼
┌──────────┐ ┌──────────┐
│ paid │ │ failed │
└──────────┘ └──────────┘
A separate skipped status exists for pay periods that were intentionally skipped without creating a payroll.
Status Definitions
| Status | Meaning | Mutable? |
|---|---|---|
draft | The payroll has been created but not yet approved. You can edit, preview, or delete it. | Yes |
pending | The payroll has been approved and is queued for processing on the payday date. | No |
processing | The payment processor is actively running the payroll. | No |
paid | All payments have been completed successfully. | No |
failed | Something went wrong during processing. | No |
reopened | A previously approved payroll was reverted for editing. It behaves like a draft. | Yes |
skipped | The pay period was skipped — no payroll was run. | No |
Transitions
draft → pending
Trigger: POST /payrolls/:id/approve
When you approve a draft, the system submits it to the payment processor, assigns check numbers for manual-pay employees, creates PTO accruals, and sends confirmation notifications. The payroll is now locked and will be processed on the payday date.
pending → processing
This transition happens automatically when the payment processor begins work — typically on the business day(s) before payday, depending on the company's processing period (1-day, 2-day, or 3-day).
processing → paid
The payment processor completed successfully. Employee direct deposits have been initiated and paper checks are ready. At this point you can download pay stubs and check data.
processing → failed
Something went wrong during processing — for example, an issue with the company's bank account or a compliance hold. The payroll will not be retried automatically.
pending → reopened
If a payroll needs changes after approval but before it starts processing, it can be reopened. This reverts it to an editable state (similar to draft).
draft → (deleted)
Trigger: DELETE /payrolls/:id
Discarding a draft removes it entirely. The pay period becomes available for a new payroll run.
What You Can Do at Each Stage
| Action | Endpoint | Allowed statuses |
|---|---|---|
| Preview cost breakdown | GET /payrolls/:id/preview | draft, reopened |
| Update earnings | PATCH /payrolls/:id | draft, reopened |
| Delete draft | DELETE /payrolls/:id | draft, reopened |
| Approve for processing | POST /payrolls/:id/approve | draft, reopened |
| View payroll details | GET /payrolls/:id | Any status |
| Download pay stubs | GET /payrolls/:id/paystubs | paid |
| Download check data | GET /payrolls/:id/checks | paid |
Tracking Status via the API
Poll a specific payroll
GET /payrolls/:id
The response includes a status field reflecting the current lifecycle stage.
Filter the payroll list by status
GET /payrolls?status=pending
This is useful for building dashboards — for example, showing all payrolls awaiting processing or surfacing any that have failed.
Tracking Status via Webhooks
If you've registered a webhook endpoint, Friday pushes an event at every lifecycle transition. This is the recommended way to track payrolls in real time — no polling required.
| Event | Fires when |
|---|---|
payroll.created | A draft is created |
payroll.updated | A draft is modified |
payroll.approved | A payroll is approved for processing |
payroll.processing | The payment processor has started |
payroll.paid | Payroll completed successfully |
payroll.failed | Processing encountered an error |
payroll.reopened | An approved payroll is reverted to draft |
payroll.deleted | A draft is discarded |
payroll.skipped | A pay period is skipped |
Each event payload includes the full payroll object (same shape as GET /payrolls/:id), so you can read the updated status and totals directly from the webhook — no follow-up API call needed.
See the Subscribing to Webhooks guide for setup instructions and signature verification.
Common Questions
Can a failed payroll be retried? Not through the API. If a payroll fails, coordinate with the company admin to resolve the underlying issue (e.g., bank account hold) and create a new payroll for the same period.
How long does processing take?
It depends on the company's processing period — typically 1 to 3 business days before payday. The payroll.paid webhook fires as soon as processing completes.
Can I tell whether a payroll is about to start processing?
The pending status means the payroll is approved and queued. The payroll.processing webhook will fire when it actually begins. There's no separate "scheduled" status in between.
What happens to a reopened payroll? It returns to an editable state. You can update earnings, preview the cost breakdown, and approve it again — the same workflow as a new draft.
Updated about 2 months ago
