Payable lifecycle and statuses
The payment status, payer approval, and payee review fields on a Wingspan V3 payable, what each value means, and which actions change them.
This page explains the three status fields on a payable, what each value means, and which API calls move a payable from one state to the next. V1's single invoice status plus client and member workflow statuses map onto these three fields.
Three independent fields
A payable carries three status fields because three different parties make decisions about it.
| Field | Who controls it | Values |
|---|---|---|
status | Wingspan, in response to your actions and to money movement | Created, Opened, Pending, PaymentInTransit, Paid, PartiallyPaid, PaidOffPlatform, Cancelled, Refunded, PartiallyRefunded, Returned |
payerApprovalStatus | You, the payer | Pending, PreApproved, Approved, Declined |
payeeReviewStatus | The payee | Pending, Accepted, Disputed, Resubmitted |
Approving a payable doesn't change its status. A payable can be Opened and Approved at the same time, which is exactly what a payroll run looks for.
Payment status
stateDiagram-v2
[*] --> Created
Created --> Opened: open
Created --> [*]: delete
Created --> Cancelled: cancel
Opened --> Pending: payment blocked
Pending --> Opened: blocker cleared
Opened --> PaymentInTransit: pay or payroll run
PaymentInTransit --> Paid
PaymentInTransit --> PartiallyPaid
PaymentInTransit --> Returned: bank return
Opened --> PaidOffPlatform: pay-off-platform
Opened --> Cancelled: cancel
Paid --> Refunded: refund
Paid --> PartiallyRefunded: partial refund
Paid --> Returned: bank return
| Status | What it means | What you can do |
|---|---|---|
Created | A draft. The payee can't see it and it can't be paid. (V1: Draft.) | Edit it, open it, cancel it, or delete it. |
Opened | Finalized and visible to the payee as an invoice. Ready to be approved and paid. A past-due payable stays Opened; there is no Overdue status on a payable. (V1: Open, Overdue.) | Approve, pay, record an off-platform payment, send a reminder, or cancel. |
Pending | Opened, but something is blocking payment. Usually the payee's engagement hasn't met its payment eligibility requirements, such as a missing payout method or tax information. pendingStatusReason names the blocker. | Find and fix the blocker. See Find incomplete payables. |
PaymentInTransit | Payment has started. The amount, funding source, and payout routes are now locked. | Wait. Watch for Paid or Returned. |
Paid | Wingspan's internal state shows the payable paid. | Reconcile. Refund if needed. |
PartiallyPaid | Part of the amount has been paid. | Reconcile. |
PaidOffPlatform | You recorded that you paid outside Wingspan. | Nothing further in Wingspan. |
Cancelled | Stopped before payment. | Nothing further. Create a new payable if you still owe the payee. |
Refunded, PartiallyRefunded | A refund has been issued against the payment. | See Refunds and returns. |
Returned | The payment was sent back by the bank. This is terminal for this payable. | Create a new payable for the replacement payment. See Refunds and returns. |
When a payable moves from Created to Opened, Wingspan assigns its invoiceNumber.
Why a payable is pending
While a payable is Pending, its read-only pendingStatusReason field records why Wingspan's eligibility check held it, such as MemberPayoutMethodNotSelected or PayeeTaxVerificationPending. In every other status it's null. A null on a Pending payable means no reason was recorded, not that the payable is clear to pay. See Find incomplete payables for every value and how to clear it.
Paid and deposit confirmation
Paid is Wingspan's internal state. DepositConfirmed means Wingspan's originating bank or provider reported its terminal processed state. It never means the recipient's bank received the money, funds are available, or the payment can't be returned. On a payable, deposit confirmation appears as events.depositConfirmedAt, separate from events.paidAt. The Payable.DepositConfirmed webhook isn't subscribable yet, so read the payable to check it. See Paid vs DepositConfirmed.
Actions that change status
State changes are always a POST to a verb on the payable, never a status value in a PATCH. The verb records what happened (an approval, a cancellation, a payment) instead of only the resulting value, which is what makes the events and actors history trustworthy.
| Action | Endpoint | Valid from | Result |
|---|---|---|---|
| Open | POST /v3/payments/payables/{payableId}/open | Created | Opened. Requires If-Match. Returns 409 EligibilityBlocked if the payee's engagement isn't payments eligible. |
| Pay | POST /v3/payments/payables/{payableId}/pay | Opened and Approved | PaymentInTransit, then Paid. Requires Idempotency-Key. |
| Record off-platform payment | POST /v3/payments/payables/{payableId}/pay-off-platform | Unpaid | PaidOffPlatform. |
| Cancel | POST /v3/payments/payables/{payableId}/cancel | Before payment | Cancelled. Returns 409 if already Paid or Cancelled. |
| Delete | DELETE /v3/payments/payables/{payableId} | Created only | Removed (204). Any other status returns 409; cancel instead. |
| Refund | POST /v3/payments/payables/{payableId}/refund | Paid and deposited | Refunded or PartiallyRefunded. |
These actions notify the payee without changing status:
POST /v3/payments/payables/{payableId}/sendemails the payee about anOpenedpayable. You can include acustomMessage.POST /v3/payments/payables/{payableId}/remindsends a reminder about anOpenedpayable.
Payer approval
Set your approval decision with PATCH /v3/payments/payables/{payableId}/workflow-status. It works on Opened and Pending payables.
curl -X PATCH "https://api.wingspan.app/v3/payments/payables/Hb4Xk9Qw2Rt7Vn1Mz8Pc3L/workflow-status" \
-H "Authorization: Bearer $WINGSPAN_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "payerApprovalStatus": "Approved", "reason": "Hours verified against timesheet" }'| Value | Meaning |
|---|---|
Pending | No decision yet. Send null to reset a payable back to Pending. |
PreApproved | A first-stage approval, for teams that approve in two steps. Payroll runs don't select it. |
Approved | Final approval. Only Approved payables are selected into payroll runs. |
Declined | You won't pay it as submitted. |
Approval doesn't bypass eligibility. A direct pay still checks that the payee's engagement is payments eligible. V1 required approvals in the app; in V3 you can approve through the API.
Payee review
Payees act on the invoice side of the same document. You'll see their decisions in payeeReviewStatus and events.
- Accept. The payee confirms the amount and terms of an
Openedpayable.payeeReviewStatusbecomesAccepted. - Reject. The payee sends an
Openedpayable back for correction, with a requiredreason. - Dispute. The payee disputes a payable after accepting it. Payment processing stops until the dispute is resolved, and
events.disputedAtis set. - Resubmit. After you decline, the payee can revise and resubmit.
payeeReviewStatusbecomesResubmitted.
Contractor acceptance before payment isn't turned on for every payer. Contact your Wingspan account manager to enable it.
Reading the fields together
| What you see | What it means |
|---|---|
Opened, payerApprovalStatus: Pending | Waiting on your approval. |
Opened, payerApprovalStatus: Approved | Ready to pay. The next payroll run you create with ApprovedPayables will pick it up, or pay it directly. |
Pending, any approval | Blocked on the payee side. Read pendingStatusReason, then see Find incomplete payables. |
payeeReviewStatus: Disputed | The payee disputed it. Resolve with them before paying. |
payeeReviewStatus: Resubmitted | The payee revised it after you declined. Review and approve or decline again. |
PaymentInTransit | Money is moving. You can't change it now. |
Webhooks
These payable events are available to subscribe to today:
| Event | Fires when |
|---|---|
Payable.Paid | The payable reaches Paid. |
Payable.PartiallyPaid | Part of the payable is paid. |
Payable.Returned | The payment is returned. |
Other transitions are recorded in the payable's events timestamps but don't have subscribable webhooks yet, including Payable.Opened, Payable.WorkflowStatusChanged, and Payable.DepositConfirmed. Read the payable to check them. See Event types for the current list.
Common mistakes
- Sending
statusin aPATCH. It's rejected. Use the action endpoints. - Retrying
openwithoutIf-Match.open,accept,reject, andPATCHrequire the payable's currentETag(or*). A stale ETag returns412withcode: PreconditionFailed; read the payable again and retry. - Assuming
Paidmeans the contractor has the money. It doesn't. A bank can still return the payment. - Retrying a
Returnedpayable. You can't pay a returned payable again or switch its funding source. Create a new payable.
Related pages
- Create a payable
- Payroll runs
- Find incomplete payables
- Invoice lifecycle for the payee's view
Updated 10 days ago