Components of an invoice
Reference for every field on a V3 invoice, including line items, splits, late fees, card-fee handling, notifications, and read-only payment data.
Use this page to look up what each part of a V3 invoice does and which fields you can set when you
create or update one. For the calls themselves, see Create an invoice.
Field names follow V3 conventions: camelCase, TitleCase enum values, money as decimal numbers in the
invoice's currency (95.00, never cents), and dates as YYYY-MM-DD. See
Request and response conventions.
Who the invoice is billed to
Send exactly one of these on create. Sending none, or more than one, returns 422 ValidationError.
| Field | Use it when |
|---|---|
payerId | You bill a Payer record directly. Wingspan uses (or creates) that relationship's default engagement. This is the common case. |
payerEngagementId | You track separate engagements or projects under one Payer and want the invoice attributed to one of them. |
payeeEngagementId | You have an existing client integration that already sends this field. New integrations should use payerId or payerEngagementId. |
The client's company name, contact name, and email live on the Payer record, not on the invoice.
In V1 you typed them into each invoice. See Create an invoice.
Core fields
| Field | Required on create | Type | Notes |
|---|---|---|---|
currency | Yes | enum | One of USD, CAD, CZK, EUR, GBP, INR, PLN. Applies to every amount on the invoice. |
lineItems | Yes | array | What you're billing for. See Line items. |
dueDate | Yes | date | The date payment is due. After it passes, an unpaid invoice becomes Overdue. |
invoiceNumber | No | string | Your invoice number. It must be unique among your invoices. If you leave it out, Wingspan generates one. |
externalId | No | string | Your own ID for reconciliation, such as the invoice ID in your accounting system. Echoed on every read and filterable with filter[externalId][eq]. A duplicate returns 409 ResourceConflict. Create is never an upsert. |
notes | No | string | Free-text notes shown on the invoice. |
metadata | No | object | Your key-value pairs, up to 50 keys with values up to 500 characters. A good place for a project name or PO number. |
Line items
Each entry in lineItems is one charge. The invoice amount is calculated from them.
| Field | Notes |
|---|---|
description | What the charge is for. |
lineItemType | Services, Expense, Reimbursement, Bonus, Commission, or Custom. Use Reimbursement or Expense for costs you're passing through. In V1 this was the reimbursableExpense checkbox. |
totalCost | A flat amount for the line. Use this or quantity with unitCost, not both. |
quantity, unitCost, unit | Hourly or per-unit billing. For example, quantity: 40, unit: "hours", unitCost: 95.00. |
detail | A second line of text shown under the description. |
discount | { percentage } or { amount }, plus an optional description. Sending both percentage and amount returns 422 with ConflictingFields. |
accounting | Optional bookkeeping dimensions: glAccountCode, class, location, project, item, taxCode. Wingspan stores these as you send them. |
splits | Per-line collaborator splits. See Collaborator splits. |
metadata | Key-value pairs for this line. |
Line-item externalId isn't supported on create yet. Sending it returns 422.
Collaborator splits
A split sends part of an invoice's proceeds to someone you work with, such as a subcontractor. It
replaces the V1 collaborators array.
"splits": [
{
"payeeId": "Wd8Lq3Vn6Kz1Xt4Rb7Mp2c",
"payeeEngagementId": "Rz5Kq2Wn8Lv4Xt1Bm7Pd3c",
"amount": 1200.00,
"currency": "USD",
"description": "Illustration work, phase 2"
}
]payeeIdandpayeeEngagementIdare required and must describe the same relationship: your
Payee record for the collaborator and its engagement. See Payees.currencymust match the invoice currency,amountmust be greater than zero, and the split
amounts can't add up to more than the invoice (or line) amount.- Put splits at the invoice level (
splits) or on individual lines (lineItems[].splits), not both. - When you send the invoice, Wingspan creates one child
Payableper split and fills in
splits[].payableId. Splits can't be changed after the invoice is sent. - A split is not a way to route your own payout across your own bank accounts. That's handled by
your payout settings. See Payout methods.
Important: Collecting a split invoice with
POST /v3/payments/invoices/{invoiceId}/pay
isn't available in the V3 API yet. The call returns409. Contact support if you need to collect
split invoices through the API.
For a full marketplace example (bill the client, pay the workers, keep the margin), see the
marketplace bill-and-pay recipe.
Payment options
| Field | Notes |
|---|---|
acceptedPaymentMethods | Which ways the payer may pay: Ach (bank debit), Credit (card), Manual (the payer sends a wire or ACH credit). If you leave it out, the invoice inherits the defaults from the engagement or Payer. |
creditFeeHandling | Who pays the card processing fee. Either split it with payeeFeePercentage and payerFeePercentage (adding up to 100), or set payerFlatFeePercentage to charge the payer a flat percentage. Sending both forms returns 422 with ConflictingFields. |
lateFeeHandling | A fee added while the invoice is overdue: lateFeePercentage (of the outstanding balance) or lateFeeAmount, plus frequency: { interval, every } where interval is LateFeeIntervalWeekly or LateFeeIntervalMonthly. For example, every: 2 with LateFeeIntervalWeekly assesses the fee every two weeks. |
Collect payment explains how the payer pays with each method.
Notifications
notificationPreferences controls the emails Wingspan sends for this invoice.
| Field | When true |
|---|---|
shouldSendInvoice | Email the invoice to the payer when it's sent. |
shouldSendReceipt | Email a receipt when it's paid. |
shouldSendReminders | Send due-date and overdue reminder emails. |
You can also send a reminder on demand with POST /v3/payments/invoices/{invoiceId}/remind.
Attachments
Invoices don't accept file uploads. Upload the file to the vault first with
POST /v3/compliance/vault-files, then attach it by ID with
POST /v3/payments/invoices/{invoiceId}/attachments and a body of { "memberFileId": "<fileId>" }.
Attaching a private file gives the payer ongoing read access to it, and detaching the file later
doesn't remove that access. See Files and documents.
Accounting sync
If you use the QuickBooks Online integration, the quickbooks object links an invoice to a
QuickBooks record created outside Wingspan, or stops Wingspan from syncing that invoice itself. See
QuickBooks Online.
Read-only fields
Wingspan sets these. You can't write them.
| Field | What it tells you |
|---|---|
id | The invoice ID. |
accountId | Your Account, the issuing payee. |
payeeId, payerId | The relationship records on each side. These are never Account IDs. |
payeeAccountId, payerAccountId | The resolved Accounts, or null until the relationship is linked. |
status | Where the invoice is in its lifecycle. See Invoice lifecycle. |
payerApprovalStatus | The payer's approval workflow: Pending, PreApproved, Approved, Declined. |
payeeReviewStatus | The payee's review workflow: Pending, Accepted, Disputed, Resubmitted. |
amount | The contractual invoice amount. It doesn't change to include fees charged to the payer. |
fees | Always present. chargedToPayer, chargedToPayee, and itemized items[] (Processing, Late, Card, InstantPayout). |
amountDetails | Settled totals: paid, fees, deductions, payouts, refunds. Money in is positive and money out is negative, so the five add up to zero. It's left out until settlement is complete. |
taxWithholdingRate | The withholding rate applied when the invoice settled, if any. |
scheduledPaymentDate | The date the payer scheduled payment for, taken from the payer's side. |
payments[] | One entry per collection attempt, with its method, status (Pending, Processing, Completed, Failed, Cancelled, Returned), amount, and statusReason on failure. The payer's bank or card is shown only as a type, institution, and mask. |
refunds[], payouts[] | Refunds issued and payout legs funded by this invoice. |
payerInvoiceViewToken | Returned only to you as the issuer. It builds the no-login payer view. Treat it as a secret. |
recurringInvoiceId, workLogId, sourceWorkLogIds, deductionIds, invoiceCreditIds | Links to the resources that produced or adjusted this invoice. |
events | Timestamps for each transition, such as openedAt, paidAt, depositedAt, overdueAt, cancelledAt. |
actors | Who made each transition, such as createdBy and paidBy. |
events.paidAt and events.depositedAt mean different things. paidAt records that Wingspan's
system marked the invoice paid. depositedAt records that Wingspan's originating bank or payment
provider reported its final processed status for the payment. Neither one means the money reached
the recipient's bank account, that funds are available, or that the payment can't be returned. See
Paid vs DepositConfirmed.
Related pages
- Invoices overview
- Create an invoice
- Recurring invoices, which use a template with most of these fields
Updated 10 days ago