Funding and Ledger Accounts
Find the ledger account your payouts are paid from, check its balance, and reconcile its transactions.
A ledger account holds the money you pay out from. Every payment is paid from exactly one ledger account, in that account's currency. This page shows how to find your accounts, read their balance and history, and what happens when an account runs short.
Before you start
- Payment Labs opens your ledger accounts when your account is set up, one per currency you pay out in. You cannot create one through the API.
- You fund an account by sending money to the bank details Payment Labs gives you for it. Funding happens outside the API; contact Payment Labs for the funding instructions of each account.
- The operations on this page need any payout role.
Step 1: List your ledger accounts
Call List Ledger Accounts. Archived accounts are left out unless you send showArchived=true.
curl https://api-sandbox.paymentlabs.io/payors/me/ledgers \
-H "Authorization: Bearer $TOKEN"[
{
"id": "A-01JD8ZK3V6M2Q4R7T9W1X3Y5Z7",
"alias": "usd-main",
"currency": "USD",
"accountNumber": "100200300",
"balance": { "value": 25000, "currency": "USD", "formattedValue": "$25,000.00", "digits": 2, "wholeValue": 2500000 },
"lastRowId": "L-01JDB2C3D4E5F6G7H8J9K0M1N2",
"archived": false
}
]lastRowId is the ID of the account's most recent transaction row; it changes whenever the balance moves, so you can compare it with a saved value to see whether there is new activity before you read the history.
Keep the id (or the alias) of each account. You pass it as ledgerAccount when you create a payment. Both forms are accepted. If you have exactly one active account you can leave ledgerAccount out and that account is used.
Get Payor also returns your accounts and balances in ledgerAccounts.
Step 2: Read the transaction history
Call Get Ledger Account Transactions with a date range to get the movements on one account.
curl "https://api-sandbox.paymentlabs.io/payors/me/ledgers/A-01JD8ZK3V6M2Q4R7T9W1X3Y5Z7?startDate=2026-10-01&endDate=2026-10-31&enrich=true" \
-H "Authorization: Bearer $TOKEN"startDateandendDatego together, and the range can cover at most 90 days. Without them you get the account and its balance only.- The response adds
startingBalance,endingBalanceandrows. Each row has anid, atimestamp, amemo, a signedamountand astatus:DRAFT,PENDING,COMPLETED,REFUNDEDorCANCELLED. enrich=trueadds details about the payment or deposit behind each row. Itscommentslists changes made to the payment after it was created: a new category, a new tax jurisdiction, or the original amount (in minor units) when the amount changed.- Rows come newest first, up to 1,000 per response. When the response includes
nextStartDate, there are older rows left in the range: call again with the samestartDateand withendDateset tonextStartDate. Repeat untilnextStartDateis absent. Paging repeats rows from the day ofnextStartDate, so de-duplicate by each row'sid. A single day with more than 1,000 rows cannot be paged past this way. - For a full history, or for busy days, use Export Ledger Transactions instead (see Step 3).
Step 3: Export statements
| You want | Call |
|---|---|
| A PDF statement for a period | Export Ledger Statement with startDate and endDate (both required, at most 90 days apart). The response is the PDF file. |
| The transaction history as a spreadsheet | Export Ledger Transactions with startDate, endDate, format (csv or xlsx, default csv) and an optional timezoneOffset in minutes (from -840 to 720). The response is { "fileUrl": "..." }, a short-lived download link. Download the file straight away. |
Know when funds arrive
Subscribe to the ledger-account-credited webhook. It fires when money lands on one of your ledger accounts and carries the amount credited, the new balance and the ledgerAccountId.
How payments use the balance
- When you submit a single payment, Payment Labs checks that the account balance covers the payment's
sourceAmount. If it does not, the call fails with423andcode: INSUFFICIENT_BALANCEand nothing is queued. - That check does not include fees. A payment that passes it can still be short once fees are added. It then waits for funds: its status stays
SUBMITTED, and it is sent automatically after your next deposit arrives. A payment that staysSUBMITTEDlonger than you expect usually means the account needs funding. - Submitting a whole batch does not check the balance up front. Every payment that cannot be covered waits for funds in the same way.
- When a payment is returned, the returned amount goes back to the ledger account it was paid from. See Payment Statuses.
Errors and edge cases
| Error | Meaning | What to do |
|---|---|---|
400 START_DATE_AND_END_DATE_REQUIRED_TOGETHER | You sent one date without the other on Get Ledger Account Transactions. | Send both or neither. |
400 START_DATE_AND_END_DATE_REQUIRED | An export was called without both dates. | Send both. |
400 START_DATE_INVALID_DATE_FORMAT, 400 END_DATE_INVALID_DATE_FORMAT | A date could not be read. | Use YYYY-MM-DD or a full ISO 8601 timestamp. |
400 START_DATE_LATER_THAN_END_DATE | The range is reversed. | Swap the dates. |
400 DATE_RANGE_TOO_LONG | The range is longer than 90 days. | Split it into several calls. |
400 INVALID_FORMAT, 400 INVALID_TIMEZONE_OFFSET | Bad format or timezoneOffset on the spreadsheet export. | Use csv or xlsx, and an offset from -840 to 720. |
404 NOT_FOUND | The account is not one of yours. | Check the id against List Ledger Accounts. |
400 VALIDATION_ERROR on Create Payment, with details.ledgerAccount[0].code = MORE_THAN_ONE_LEDGER_ACCOUNT | You left ledgerAccount out and you have more than one active account. | Send ledgerAccount. |
Same, with code INVALID_LEDGER_ACCOUNT | The ledgerAccount you sent is not one of your active accounts. constraints.validAccounts lists the aliases you can use. | Send one of those. |
Next steps
Updated 1 day ago
What’s Next
Next: Payment Methods and Costs.
