Skip to main content

Recording customer payments

A customer payment is an incoming remittance from a shipper/customer applied against their receivable invoices. It has two levels:
  • The payment (pym_…) — the money that arrived: an amount, a currency, a transaction date, and the check/ACH reference it came in on.
  • Its line items (pli_…) — how that money is split across your invoices. Each line item applies an amount to a specific invoice (inv_…) for a specific customer (cus_…).
This page covers creating a payment with its line items, reading it back, and reconciling it against receivables. For the complete data contract that keeps statements and customer balances accurate, see Accounts receivable integration requirements.
This is the accounts-receivable (money in) side. For paying carriers (money out) the resource is bill-payments, which is a separate endpoint family. For the AR concepts behind these records — reconciliation, short-pays, and the like — see Remittances Management and Accounts Receivable Management.
All amounts are integer cents. totalAmount: 1120000 is $11,200.00, not eleven million dollars. This matches every monetary field in the Upwell API.

Create a payment with its line items

The primary flow is a single POST /api/rest/customer_payments that inserts the payment and its line items together, using a nested paymentLineItems.data array:
When line items are nested under the payment like this, omit paymentId on each line item — the parent payment supplies the link. Fields you don’t set come back null.

Required fields

Field reference

Payment (pym_…) Line item (pli_…)
The line-item amounts don’t have to sum to the payment’s totalAmount — a remittance can be partially applied and reconciled later. For the complete column list, see the customer_payments and customer_payment_line_items entries in the API Reference.

Two different status fields

These are not the same field, and the difference matters:
  • Payment status is optional and drawn from PaymentStatusesEnum: PENDING, SUCCEEDED, FAILED, DISPUTED, REFUNDED, PAYMENT_REVERSED — each defined in the Vocabulary. Most imported payments leave it unset; read an unset value as SUCCEEDED for display and reconciliation.
  • Line-item status is a required free-form string, not a fixed enum. In practice it carries reconciliation states like applied, paid, or completed. Don’t assume a closed set of values or a fixed casing.
In the standard API-managed balance model, neither status field decides whether a line-item amount counts against the invoice. Linking the line item to an invoice applies its amount. Do not create a pending or failed application with a nonzero amount and expect its status to keep the invoice unchanged.

Read payments back

To filter or sort, use POST /api/rest/customer_payments/search with a Hasura-style where:

Create many at once

POST /api/rest/bulk-customer-payments inserts an array of payments in one call. The response is a Hasura mutation envelope — read the created rows from returning:

Update and delete

Line items on their own

If you’d rather attach line items to an existing payment (or manage them independently), use the line-item endpoints directly — GET/POST /api/rest/customer_payment_line_items and .../customer_payment_line_items/{id}. Here, set paymentId explicitly to link the line item to its payment:
POST /api/rest/bulk-customer-payment-line-items bulk-creates several at once, the same { "inputs": [...] } shape as bulk-customer-payments:

How applications update invoices

Creating, changing, or deleting a linked payment line item automatically recalculates the target invoice in the standard API-managed model:
A remaining balance between zero and the invoice total produces PART_PAID; zero or less produces PAID. Removing the application reopens a previously paid or partially paid invoice when its full balance is due again. A payment header without an invoice-linked line item does not change any invoice.
If totalAmountWithFees is present, Upwell uses it instead of totalAmount for the application. Do not use it for a gross amount that includes processing fees; that would overstate the cash applied to the invoice.

Correct or reverse an application

Update the original line item’s amount when the allocation was wrong. Delete it when the application should no longer exist:
Changing only status does not reverse the amount. Preserve the line-item ID or its stable source key so corrections and returns update the original application instead of creating a second one.

Idempotency and deduplication

If you set sourceSystem and sourceSystemId, the pair is unique per tenant — within your organization no two payments can share it, and no two line items can either. Use your own remittance/transaction reference as sourceSystemId so re-posting the same remittance conflicts instead of creating a duplicate — a simple idempotency key for retried imports. For payment line items, use a key that identifies the individual application, not only the parent remittance. One payment can be split across several invoices, and each application must be independently correctable.
Testing against staging? Use the staging base URL https://staging.api.upwell.com with your staging API key — the paths are identical, and keys are environment-specific. See Environments for how staging access is provisioned.
For the complete request and response schemas, see the customer_payments and customer_payment_line_items entries in the API Reference. To submit carrier invoices (the payables side) instead, see Submitting carrier invoices via API.