Reports

Generate a report file, download it, and read the Payables and Worker report rows as JSON with the V3 API.

The V3 API has two kinds of reports:

  • Report files. You ask for a report by type, Wingspan generates it in the background, and you download a file.
  • Report rows. You read the Payables Report and the Worker Report directly as paginated JSON, one row per Payable or per payee.

Prerequisites

  • For report files, platform.report:write to generate and platform.report:read to read and download.
  • For rows, payments.payable-report:read for the Payables Report and payments.contractor-report:read for the Worker Report.

Report files

PurposeMethod and path
Generate a reportPOST /v3/platform/reports
List reportsGET /v3/platform/reports
Get a reportGET /v3/platform/reports/{reportId}
Download the fileGET /v3/platform/reports/{reportId}/file
Get a download linkGET /v3/platform/reports/{reportId}/file-url

Generate a report

FieldTypeNotes
typeenumRequired. AgingPayables, AgingInvoices, PayeeSummary, PayrollJournal, TaxLiability, ProfitAndLoss, TaxEstimate or WorkerActivity.
formatenumCsv, Pdf or Xlsx.
parametersobjectInputs for the report type.
metadataobjectYour own key-value data.
curl -X POST https://api.wingspan.app/v3/platform/reports \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "X-Wingspan-Account: Nw7kQ2pLx9RtVb3mHc5dZa" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "type": "AgingPayables", "format": "Csv" }'

The response is 202. The report has status: Processing and a progress object with total, completed and failed. Poll Get a report until status is Completed or Failed.

Download the file

Download the file answers 302 with a Location header that points to a short-lived signed URL. Use Get a download link when your client cannot follow a redirect, such as a browser page that has to navigate to the file. It returns { "url": "...", "expiresAt": "..." }. Do not store the link. It stops working at expiresAt.

GET .../file returns 409 while the report is not Completed.

Payables Report rows

List Payables Report rows: GET /v3/reports/payables. It returns one row for each Payable on the Account, with the same Payables and filters as GET /v3/payments/payables.

ParameterNotes
filter[status][eq], filter[status][anyOf][]Created, Opened, PaymentInTransit, Paid, PartiallyPaid, Cancelled, Refunded, PartiallyRefunded, PaidOffPlatform, Returned, Pending
filter[payerApprovalStatus][eq], [anyOf][]Pending, PreApproved, Approved, Declined
filter[dueDate][gte], filter[dueDate][lte]Dates, YYYY-MM-DD
filter[payeeAccountId][eq], filter[parentInvoiceId][eq], filter[payrollRunId][eq]Exact match
filter[includeDescendants]true adds sub-accounts where you may run the report.
agingWeekly or Monthly. Adds aging.ageGroup and aging.daysPastDue to each row.

Each row has id, accountId, payable, payee, engagement, approvals, documents (invoicePdfUrl, receiptPdfUrl), payout.destination, aging, customFields, purchaseOrderNumber and events.sentAt.

curl -g "https://api.wingspan.app/v3/reports/payables?filter[status][anyOf][]=Opened&filter[dueDate][lte]=2026-11-30&aging=Weekly&page[size]=50" \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "X-Wingspan-Account: Nw7kQ2pLx9RtVb3mHc5dZa"

Worker Report rows

PurposeMethod and path
List Worker Report rowsGET /v3/reports/payees
List Worker Payables Summary rowsGET /v3/reports/payees/payables-summary

Both return one row per payee. Filters: filter[status][eq] (Activated or Deactivated; omit it for all payees) and filter[includeDescendants]. The summary route also takes filter[paidAt][gte] and filter[paidAt][lte]. The range limits the totals, not the rows: every payee is listed, with zero counts when nothing was paid. A date-only lte includes that whole day in UTC.

A row has payee, taxIdentifiers, engagements, customFields, incomeAndExpensesEnabled, taxWithholdingsEnabled and events (signedUpAt, payoutMethodFirstAddedAt). A tax identifier shows only countryCode, type (SSN or EIN), hasValue and tinLastFour. An SSN's tinLastFour is returned only to callers with Admin authority on the row's Account. In the summary, payablesSummary has paidPayablesCount, firstPaidAt, lastPaidAt, withholdingsCount and totals per currency (paidAmount, withheldAmount).

pagination.totalSize is returned on the first page only.

Errors

StatusCause
401, 403Missing credentials, or the credential lacks the scope.
404Report not found.
409You asked for the file of a report that is not Completed.
422A body field or filter value is invalid, such as an unknown report type.

Did this page help you?