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.

FieldWho controls itValues
statusWingspan, in response to your actions and to money movementCreated, Opened, Pending, PaymentInTransit, Paid, PartiallyPaid, PaidOffPlatform, Cancelled, Refunded, PartiallyRefunded, Returned
payerApprovalStatusYou, the payerPending, PreApproved, Approved, Declined
payeeReviewStatusThe payeePending, 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
StatusWhat it meansWhat you can do
CreatedA draft. The payee can't see it and it can't be paid. (V1: Draft.)Edit it, open it, cancel it, or delete it.
OpenedFinalized 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.
PendingOpened, 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.
PaymentInTransitPayment has started. The amount, funding source, and payout routes are now locked.Wait. Watch for Paid or Returned.
PaidWingspan's internal state shows the payable paid.Reconcile. Refund if needed.
PartiallyPaidPart of the amount has been paid.Reconcile.
PaidOffPlatformYou recorded that you paid outside Wingspan.Nothing further in Wingspan.
CancelledStopped before payment.Nothing further. Create a new payable if you still owe the payee.
Refunded, PartiallyRefundedA refund has been issued against the payment.See Refunds and returns.
ReturnedThe 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.

ActionEndpointValid fromResult
OpenPOST /v3/payments/payables/{payableId}/openCreatedOpened. Requires If-Match. Returns 409 EligibilityBlocked if the payee's engagement isn't payments eligible.
PayPOST /v3/payments/payables/{payableId}/payOpened and ApprovedPaymentInTransit, then Paid. Requires Idempotency-Key.
Record off-platform paymentPOST /v3/payments/payables/{payableId}/pay-off-platformUnpaidPaidOffPlatform.
CancelPOST /v3/payments/payables/{payableId}/cancelBefore paymentCancelled. Returns 409 if already Paid or Cancelled.
DeleteDELETE /v3/payments/payables/{payableId}Created onlyRemoved (204). Any other status returns 409; cancel instead.
RefundPOST /v3/payments/payables/{payableId}/refundPaid and depositedRefunded or PartiallyRefunded.

These actions notify the payee without changing status:

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" }'
ValueMeaning
PendingNo decision yet. Send null to reset a payable back to Pending.
PreApprovedA first-stage approval, for teams that approve in two steps. Payroll runs don't select it.
ApprovedFinal approval. Only Approved payables are selected into payroll runs.
DeclinedYou 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 Opened payable. payeeReviewStatus becomes Accepted.
  • Reject. The payee sends an Opened payable back for correction, with a required reason.
  • Dispute. The payee disputes a payable after accepting it. Payment processing stops until the dispute is resolved, and events.disputedAt is set.
  • Resubmit. After you decline, the payee can revise and resubmit. payeeReviewStatus becomes Resubmitted.

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 seeWhat it means
Opened, payerApprovalStatus: PendingWaiting on your approval.
Opened, payerApprovalStatus: ApprovedReady to pay. The next payroll run you create with ApprovedPayables will pick it up, or pay it directly.
Pending, any approvalBlocked on the payee side. Read pendingStatusReason, then see Find incomplete payables.
payeeReviewStatus: DisputedThe payee disputed it. Resolve with them before paying.
payeeReviewStatus: ResubmittedThe payee revised it after you declined. Review and approve or decline again.
PaymentInTransitMoney is moving. You can't change it now.

Webhooks

These payable events are available to subscribe to today:

EventFires when
Payable.PaidThe payable reaches Paid.
Payable.PartiallyPaidPart of the payable is paid.
Payable.ReturnedThe 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 status in a PATCH. It's rejected. Use the action endpoints.
  • Retrying open without If-Match. open, accept, reject, and PATCH require the payable's current ETag (or *). A stale ETag returns 412 with code: PreconditionFailed; read the payable again and retry.
  • Assuming Paid means the contractor has the money. It doesn't. A bank can still return the payment.
  • Retrying a Returned payable. You can't pay a returned payable again or switch its funding source. Create a new payable.

Related pages


Did this page help you?