Lunch
Lunch Partner API

Sync receivables, one at a time or a spreadsheet at a time.


Read an invoice, and whatever advance stands against it

GET
https://api.luxor.lunchpayments.com
/v1/organizations/{payeeExternalId}/invoices/{externalId}

Nested under the business because an invoice identifier is unique per PAYEE rather than per account. Two of your customers may each number an invoice 001, so the pair is the key.

The advance is null until one is requested. Once it exists you get its state, what went out, and what is still owed. Which funder is behind it, and on what terms, is not reported: that is our arrangement with a lender rather than yours.

Read an invoice, and whatever advance stands against itpath Parameters

payeeExternalId
string · minLength: 1 · required

Your own identifier for the business, as supplied when you synced it. You never need to store a Lunch identifier.

Your own identifier for the business, as supplied when you synced it. You never need to store a Lunch identifier.

externalId
string · minLength: 1 · required

Your own identifier for the business, as supplied when you synced it. You never need to store a Lunch identifier.

Your own identifier for the business, as supplied when you synced it. You never need to store a Lunch identifier.

Read an invoice, and whatever advance stands against it Responses

The invoice

externalId
string · required
status
string · enum · required

The status YOU last synced for this invoice. Lunch never writes it; what Lunch has collected is collected and collectionState below, which move independently. An invoice can read ISSUED and COLLECTED at the same time. We may add members to this list; we never remove one or repurpose its meaning. Keep a default branch for a value you do not recognise.

Enum values:
ISSUED
PARTIALLY_PAID
PAID
VOIDED
faceValue
integer · max: 2147483647 · required

The invoice face value in integer cents. Must be positive, and at most 2147483647, which is $21,474,836.47.

collected
integer · required

Collected from the payor against this receivable, in integer cents, never more than its face value.

collectionState
string · enum · required

Where collection stands, derived from collected against faceValue. We may add members to this list; we never remove one or repurpose its meaning. Keep a default branch for a value you do not recognise.

Enum values:
UNCOLLECTED
PARTIALLY_COLLECTED
COLLECTED
issueDate
string · date-time · required
dueDate
string · date-time · required
advance
object | null · required
fundable
boolean · required

Whether an advance could be requested against this invoice right now: it is financeable, nothing already stands against it, the business has cleared all three onboarding gates, and an advance would fit its limit. The same set POST /v1/advances enforces, so a true here is not followed by a 409 there.

notFundableReason
string | null · required

Why not, in a sentence, or null when it is fundable. Never the amounts behind the limit, which span every partner serving this business.


Create or update an invoice

PUT
https://api.luxor.lunchpayments.com
/v1/invoices/{externalId}

Idempotent on your own identifier, which only has to be unique per PAYEE, since two of your customers may each number an invoice 001. Both counterparties are addressed by your identifiers too, and created if you have not synced them yet.

Once an advance has been requested against an invoice, only its STATUS can change. Money coming back is matched against the amount and dates you gave us, so a later correction would quietly re-point a payment we have already funded. The response says which happened.

Create or update an invoicepath Parameters

externalId
string · minLength: 1 · required

Your own identifier for the business, as supplied when you synced it. You never need to store a Lunch identifier.

Your own identifier for the business, as supplied when you synced it. You never need to store a Lunch identifier.

Create or update an invoice Request Body

object · required

The business owed the money.

object · required

The business that owes it.

status
string · enum · required

ISSUED is the only state an advance can be requested against.

Enum values:
ISSUED
PARTIALLY_PAID
PAID
VOIDED
faceValue
integer · max: 2147483647 · required

The invoice face value in integer cents. Must be positive, and at most 2147483647, which is $21,474,836.47.

issueDate
string · date-time · required
dueDate
string · date-time · required

Create or update an invoice Responses

The invoice, as we now hold it

externalId
string · required
outcome
string · enum · required

statusOnly means an advance exists against this invoice, so its amount and dates were left as they were and only the status moved. We may add members to this list; we never remove one or repurpose its meaning. Keep a default branch for a value you do not recognise.

Enum values:
created
updated
statusOnly
reason
string | null · required

Read what an import did

GET
https://api.luxor.lunchpayments.com
/v1/invoices/imports/{externalId}

The same report the upload returned, for as long as you keep the identifier. This is what answers "what landed?" after a dropped connection, without re-uploading anything.

Read what an import didpath Parameters

externalId
string · minLength: 1 · required

Your own identifier for the business, as supplied when you synced it. You never need to store a Lunch identifier.

Your own identifier for the business, as supplied when you synced it. You never need to store a Lunch identifier.

Read what an import did Responses

The import, and every row of it.

externalId
string · required
rowCount
integer · required
finished
boolean · required
object · required
object[] · required

Import a spreadsheet of invoices

PUT
https://api.luxor.lunchpayments.com
/v1/invoices/imports/{externalId}

A CSV of up to 1000 rows, each one doing exactly what PUT /invoices/{externalId} does, so re-uploading a file after fixing three rows changes those three and no others.

Required columns, matched by NAME so a reordered export still works: externalId, payeeLegalName, payorLegalName, status, faceValue, issueDate, dueDate. Optional: payeeExternalId and payorExternalId, plus the tax id and contact fields the single-invoice route accepts, prefixed payee/payor.

Send your own identifier for a business whenever you have one. A key is a stronger identity than a name, and it is what lets you address the business later. Leave the column out or leave the cell blank and Lunch derives a stable identifier from the legal name instead: the same name gives the same identifier on every upload, so next month's invoice for a vendor reaches the business this file created. Two vendors you name identically will become one business.

A bad row does not fail the batch: it is reported and the rest continue. The identifier you choose names this upload. Ask for it again with GET to get the same report back, and reuse it with the SAME file to finish one that was interrupted.

Import a spreadsheet of invoicespath Parameters

externalId
string · minLength: 1 · required

Your own identifier for the business, as supplied when you synced it. You never need to store a Lunch identifier.

Your own identifier for the business, as supplied when you synced it. You never need to store a Lunch identifier.

Import a spreadsheet of invoices Request Body

string

Import a spreadsheet of invoices Responses

The file was read. Every row has an outcome.

externalId
string · required
rowCount
integer · required
finished
boolean · required
object · required
object[] · required