Find incomplete payables

Find Wingspan V3 payables that can't be paid yet, read why each one is pending, and clear the blocker.

This guide shows you how to find payables that won't be paid, work out what's blocking each one, and clear the blocker. When you pay many contractors across many engagements, a few payables will get stuck, and they're easy to miss because nothing fails loudly.

Why a payable gets stuck

A payable can't be paid while the payee's engagement isn't payments eligible. Eligibility comes from the engagement's requirements, such as a signed agreement, a payout method, or verified tax information.

Where the blocker shows up depends on when it's hit:

  • Opening a payable for an ineligible engagement fails with 409 EligibilityBlocked, so the payable stays Created.
  • A payable that was opened but can't be paid shows status: Pending, and its pendingStatusReason says why.
  • In a payroll run, blocked payables are counted in breakdown.payablesStatuses.pending.

pendingStatusReason works like the V1 field of the same name (V1 kept it in metadata.pendingStatusReason). In V3 it's a read-only top-level field on the payable.

A payable that's Opened but not Approved isn't stuck; it's waiting on your approval. See Payable lifecycle and statuses.

Pending reasons

pendingStatusReason is set only while status is Pending, and null otherwise. Every value is a blocking reason.

pendingStatusReasonWhat's blocking paymentWho acts
CollaboratorMissingEligibilityRequirementA standard onboarding requirement on the engagement isn't complete.Payee, or you if it's waiting on your review
CollaboratorMissingCustomEligibilityRequirementA requirement you added, such as a signed agreement, license, or document, isn't complete.Payee, or you if it's waiting on your review
MemberPayoutMethodNotSelectedThe payee has no payout method.Payee
MemberTaxDocumentationNotVerifiedThe payee's tax information isn't verified.Payee
PayeeTaxInformationIsMissingThe payee hasn't provided tax information.Payee
PayeeTaxInformationNotSharedThe payee hasn't shared their tax information with you.Payee
PayeeTaxDocumentationNotSharedThe payee hasn't shared their tax documents with you.Payee
PayeeTaxVerificationPendingTax verification is still running.Nobody yet. Wait.
PayeeTaxVerificationFailedTax verification came back unsuccessful.Payee, with you
PayeeW9AcknowledgementMissingThe payee hasn't completed the W-9 acknowledgement.Payee
PayeeW8AcknowledgementMissingThe payee hasn't completed the W-8 acknowledgement.Payee
LocalTaxAcknowledgementMissingThe payee hasn't completed a required local tax acknowledgement.Payee

Two things to watch for:

  • A Pending payable with pendingStatusReason: null means no reason was recorded. It doesn't mean the payable is clear. Check the engagement's requirements (steps 2 and 3).
  • The enum also lists TransactionsYTDBelowThreshold and PayeeTaxVerificationSuccessful. Wingspan never returns them, so don't treat them as signs that a payable is eligible.

Handle an unrecognized value the same way as null: check the engagement.

Before you begin

You need an API token, and X-Wingspan-Account if you're working in a child Account.

Step 1: List pending payables

List them with GET /v3/payments/payables. You can't filter by pendingStatusReason, so list every Pending payable and group them by reason yourself.

curl -g "https://api.wingspan.app/v3/payments/payables?filter[status][eq]=Pending&page[size]=100" \
  -H "Authorization: Bearer $WINGSPAN_TOKEN"
// (trimmed)
{
  "data": [
    {
      "id": "Jd8Rw3Nz6Kq1Tx5Vb0Lm7Y",
      "status": "Pending",
      "pendingStatusReason": "CollaboratorMissingCustomEligibilityRequirement",
      "payerApprovalStatus": "Approved",
      "payeeId": "q7Lm2VxR9tKd4WnB8sHc1Z",
      "payeeEngagementId": "Tz3Nq8KpW1vXr6Ld0Ya5Mc",
      "externalId": "NW-AP-20477",
      "amount": 920.00,
      "dueDate": "2026-10-02"
    }
  ],
  "pagination": { "nextPageToken": "" }
}

Keep paging with page[token] until nextPageToken is "". Also check status: Created payables you tried to open: they have no pendingStatusReason, so go straight to step 2 for them.

The reason tells you what kind of blocker it is. For payout method and tax reasons, you can often go straight to step 4. For a requirement reason, a null reason, or a Created payable, note the payeeEngagementId and find the exact requirement in steps 2 and 3.

Step 2: Check the engagement

Call GET /v3/payments/payee-engagements/{payeeEngagementId}:

// (trimmed)
{
  "id": "Tz3Nq8KpW1vXr6Ld0Ya5Mc",
  "status": "Activated",
  "paymentsEligibility": "NotEligible",
  "areAllRequirementsComplete": false,
  "requirementIds": ["Rp2Xk7Lw4Qz9Tn1Mv6Hb3C", "Dn5Vk8Rt2Xq6Lm1Zw9Hb4S"]
}

paymentsEligibility: NotEligible confirms the engagement is the blocker.

Step 3: Find the incomplete requirements

List the engagement's requirements that aren't complete with GET /v3/onboarding/payee-requirements:

curl -g "https://api.wingspan.app/v3/onboarding/payee-requirements?filter[payeeEngagementId][anyOf][]=Tz3Nq8KpW1vXr6Ld0Ya5Mc&filter[status][anyOf][]=PendingCompletion&filter[status][anyOf][]=PendingPayerReview" \
  -H "Authorization: Bearer $WINGSPAN_TOKEN"
// (trimmed)
{
  "data": [
    { "id": "Rp2Xk7Lw4Qz9Tn1Mv6Hb3C", "type": "PayoutMethod", "name": "Payout method", "status": "PendingCompletion", "blockedReason": null },
    { "id": "Dn5Vk8Rt2Xq6Lm1Zw9Hb4S", "type": "Signature", "name": "Contractor agreement", "status": "PendingPayerReview", "blockedReason": "AwaitingPayerReview" }
  ],
  "pagination": { "nextPageToken": "" }
}

Step 4: Clear each blocker

What you seeWho actsWhat to do
status: PendingPayerReview, blockedReason: AwaitingPayerReviewYouThe payee submitted it and it's waiting on you. Review and approve with POST /v3/onboarding/payee-requirements/{requirementId}/approve, or reject it.
pendingStatusReason: MemberPayoutMethodNotSelected, or requirement type: PayoutMethod in PendingCompletionPayeeAsk the payee to add a payout method. For a payee without a Wingspan Account, set up payout routing for them. See Payment and payout methods.
pendingStatusReason of PayeeTaxInformationIsMissing, MemberTaxDocumentationNotVerified, or PayeeTaxVerificationFailed, or requirement type: TaxVerification in PendingCompletionPayeeAsk the payee to complete or correct their tax information. See Tax information.
pendingStatusReason of PayeeTaxInformationNotShared or PayeeTaxDocumentationNotShared, or blockedReason: TaxDocumentShareNotGrantedPayeeThe payee needs to share their tax information with you.
pendingStatusReason of PayeeW9AcknowledgementMissing, PayeeW8AcknowledgementMissing, or LocalTaxAcknowledgementMissingPayeeAsk the payee to complete the acknowledgement when they sign in. See Tax information.
pendingStatusReason: PayeeTaxVerificationPendingNobody yetTax verification is still running. Wait.
blockedReason: VendorProcessingNobody yetAn outside check is still running. Wait.
blockedReason: ExternalResultFailedYou and the payeeAn outside check came back unsuccessful. Review the result with the payee.
blockedReason: AwaitingDataSourceYouNothing is attached for the payee to act on yet. Check how the requirement is configured.
Any other PendingCompletionPayeeSend the payee a reminder to finish onboarding.

Completing or approving the last incomplete requirement makes the engagement eligible right away. See Requirements and eligibility.

Step 5: Pay the payable

Once the engagement is eligible:

  • A Created payable can now be opened. See Create a payable.
  • A Pending payable that's approved can be paid directly or picked up by your next payroll run.

Common mistakes

  • Cancelling a payroll run because some payees are pending. Fix the payees and pay those payables in a new run.
  • An engagement with no requirements that never becomes eligible. Eligibility is recalculated when a requirement is completed. If an engagement has no requirements at all, nothing triggers that. Contact support if an engagement with no requirements shows NotEligible.
  • Only checking Pending. Payables that failed to open stay Created. Check both.
  • Treating a null reason as clear to pay. On a Pending payable, null only means no reason was recorded. Check the engagement.

Related pages


Did this page help you?