Payment Imports

Create many payments in a batch from a CSV or Excel file, check every row, then turn the valid rows into payments.

A payment import turns a spreadsheet into payments in one batch. You upload the file, Payment Labs validates every row and tells you what each row will do, and you then decide whether to create the payments. Use an import when the payouts already live in a spreadsheet; when your system creates payments one by one, call Create Payment instead.

Before you start

  • You have a batch. The batch supplies the default payment category and tax jurisdiction for rows that leave them empty.
  • Imports need the Write permission; reading them needs any payout role.
  • The payments an import creates are DRAFT. Finishing an import does not submit them.

The file format

  • CSV (text/csv) or Excel .xlsx (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet). Only the first sheet of an Excel file is read.
  • One header row, then one row per payment. Rows above the header are ignored: the header is the first row that contains both an email column and an amount column. You can keep instructions or comments above it.
  • Header names must be spelled exactly as listed below (letter case included). Spaces around them are ignored. Columns with other names are ignored.
ColumnOther accepted namesRequiredContent
Email AddresspayeeEmailYesThe payee's email.
AmountPrize Payout, amountYesThe amount in the ledger account's currency, digits and a decimal point only: 1000.00, not 1,000.00 or $1000.
Payee Reference IDpayeeReferenceIdNoYour ID for the payee. See Payee Reference IDs.
Payment Reference IDReference, Reference ID, referenceIdNoYour own label for the payment.
AccountaccountWhen you have more than one ledger accountThe ledger account's alias or id, in any letter case. With one ledger account, leave it empty.
Tax JurisdictiontaxJurisdictionWhen your account has more than one jurisdiction and the batch has noneus, gb, de, fi, pl, se, sa, my or none, and enabled on your account. Defaults to the batch's.
Payment CategorypaymentCategoryNoOne of the payment categories. Defaults to the batch's.
Payee MessagePayee MemoNoA note the payee sees.
Payor MemopayorMemoNoA note only you see.
tag_<key>—NoA tag on the payment, for example a column tag_Department with the value marketing;internal. Separate several values with ;. Only accepted when tags are enabled on your account.

If you connected QuickBooks or Xero, the import also accepts their classification columns, which are passed to that integration:

ColumnOther accepted namesContent
QuickBooks CategoryCategoryQuickBooks category.
QuickBooks ClassClassQuickBooks class.
QuickBooks LocationQuickBooks Department, Location, DepartmentQuickBooks location or department.
Xero Account—Xero account.
tracking_<category>—One column per Xero tracking category, for example tracking_Region.

A minimal CSV:

Email Address,Amount,Payee Reference ID,Payment Reference ID,Payee Message
[email protected],250.00,user-1001,invoice-4471,October royalties
[email protected],1200.50,user-1002,invoice-4472,October royalties

The Payment Labs dashboard offers the same template for download from the batch import screen.

Step 1: Create the import

curl -X POST https://api-sandbox.paymentlabs.io/batches/B-01JDA1B2C3D4E5F6G7H8J9K0M1/imports \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "fileName": "october-royalties.csv", "fileMimeType": "text/csv" }'

Create Import returns 201:

{
  "importId": "I-01JDA5E6F7G8H9J0K1M2N3P4Q5",
  "fileUploadUrl": "https://..."
}

The import is created. Both fields are required, and fileMimeType must be one of the two types above.

Step 2: Upload the file

Send the file with an HTTP PUT to fileUploadUrl. Do not add your Authorization header: the URL carries its own signature.

curl -X PUT "$FILE_UPLOAD_URL" \
  -H "Content-Type: text/csv" \
  --data-binary @october-royalties.csv

The upload URL is valid for one hour. An import whose file is never uploaded is removed after a few hours.

Step 3: Wait for validation

Payment Labs starts reading the file as soon as it arrives. Poll Get Import every few seconds until status is no longer processing:

StatusMeaningNext
createdWaiting for the file.Upload it.
processingReading and validating rows.Keep polling.
readyEvery row is valid.Review, then finish.
processed_with_errorsAt least one row is invalid.Review the errors. Fix the file in a new import, or finish with importValid.
processing_failedThe file could not be read: no header row with the required columns, no data rows, or an unreadable file.Delete it and start a new import with a corrected file.
finishingCreating the payments.Keep polling.
finishedPayments are created.Submit them.

entries on the import counts rows: total, validated (rows checked so far, valid or not), failed, and processed once finishing has created payments.

To list every import of a batch, call Get Batch Imports.

Step 4: Review the rows

Get Import Rows returns the rows, 100 per page by default. When the response has nextPage, pass it as exclusiveStartId to read the next page; it is absent on the last page. totalCount is the number of rows in the file.

{
  "totalCount": 2,
  "currentCount": 2,
  "items": [
    {
      "importId": "I-01JDA5E6F7G8H9J0K1M2N3P4Q5",
      "batchId": "B-01JDA1B2C3D4E5F6G7H8J9K0M1",
      "paymentId": "P-01JDA6F7G8H9J0K1M2N3P4Q5R6",
      "payeeEmail": "[email protected]",
      "payeeReferenceId": "user-1001",
      "amount": { "value": 250, "currency": "USD", "formattedValue": "$250.00", "digits": 2, "wholeValue": 25000 },
      "valid": true,
      "userAction": "NO_CHANGE"
    },
    {
      "importId": "I-01JDA5E6F7G8H9J0K1M2N3P4Q5",
      "batchId": "B-01JDA1B2C3D4E5F6G7H8J9K0M1",
      "payeeEmail": "kenji.mori@example",
      "valid": false,
      "error": { "payeeEmail": [{ "code": "INVALID_EMAIL", "message": "..." }] }
    }
  ]
}
  • valid tells you whether the row will become a payment.
  • error maps each field to the problems found in it.
  • userAction tells you what the row does to the payee: NO_CHANGE, NEW_PAYEE, EMAIL_CHANGED or REFERENCE_CHANGED. Check every EMAIL_CHANGED and REFERENCE_CHANGED row before you finish; see Payee Reference IDs.
  • paymentId is the ID the payment will have once it is created.
  • expenseAccountName, className and locationName repeat the QuickBooks category, class and location you wrote in the row, as typed. A name your QuickBooks company does not have is reported under the same key in error, but the row stays valid: the payment is created and you can classify it later.

Common row errors: a missing or invalid email or amount, an Account that is not one of your ledger accounts (or is missing when you have several), a jurisdiction or category that is unknown or not enabled, a payee email and reference ID that belong to different payees, and the same reference ID used with two different emails in the file (INCONSISTENT_REFERENCE_ID).

Step 5: Finish the import

Finish Import creates the payments. It returns 202 and the import moves to finishing, then finished.

{ "errorHandling": "importValid" }
errorHandlingEffect
allOrNoneCreate payments only if every row is valid. On an import with errors the call returns 400 and nothing is created.
importValidCreate payments for the valid rows and skip the invalid ones.

The new payments are DRAFT. Submit them like any other payment, for example all at once with Submit Batch. See Creating and Submitting Payments.

Delete an import

Delete Import discards an import that has not been finished: one in created, ready, processed_with_errors or processing_failed. It returns 204. It creates and deletes no payments.

Errors and edge cases

ErrorOperationMeaningWhat to do
400 VALIDATION_ERRORCreatefileName or fileMimeType is missing or invalid.Fix the body.
404 NOT_FOUNDAllThe batch or import does not exist or is not yours.Check the IDs.
400 with message: "Import has failed entries"FinishYou sent allOrNone and some rows are invalid.Finish with importValid, or fix the file in a new import.
423FinishThe import is not ready or processed_with_errors.Wait for validation, or check that it is not already finished.
423 NOT_EDITABLEDeleteThe import is processing, finishing or finished.Nothing to delete.

Next steps


What’s Next

Did this page help you?