Skip to main content

Managing customer invoices

A customer invoice (inv_…) is what you bill your customer (shipper) for a shipment — the accounts-receivable side. This page covers creating invoices, adding line items and documents, and reading them back.
This is the AR (money in) side. For submitting carrier invoices (money out, AP), see Submitting carrier invoices via API. For the relationship between these objects, see Core concepts & data model.

Prerequisites

Create an invoice

POST /api/rest/invoices creates a customer invoice. The invoice is tied to a shipment and a customer:

Fields

POST is not retry-safe for invoices — re-posting an existing (sourceSystem, sourceSystemId) pair returns a 400 Uniqueness violation. Use POST for first sync, PUT for updates. See Idempotency & retries.

Add line items

POST /api/rest/invoice_line_items adds a line item to an existing invoice:
Update with PATCH /api/rest/invoice_line_items/{id}. Delete with DELETE /api/rest/invoice_line_items/{id}.

Attach documents to an invoice

Attach supporting documents (the invoice PDF, BOLs, PODs) to a customer invoice using the same presigned-upload flow as carrier invoices:
1

Request a presigned URL

POST /api/rest/generate-upload-presigned-url with associationType: "INVOICE" and associationId set to the invoice ID.
2

PUT the bytes

Upload the raw file to uploadUrl.
You can also attach documents from the shipment — documents on a shipment are automatically visible on invoices linked to that shipment, so you often don’t need to re-upload. See Working with shipment documents.
Alternatively, POST /api/rest/invoices/{invoiceId}/documents accepts base64-encoded documents directly — convenient for smaller files. For large documents, the presigned-URL flow avoids payload size limits.

Read invoices back

Search by source system

POST /api/rest/invoices/search finds invoices by their external key:
The endpoint accepts a Hasura-style where filter (plus orderBy, limit, offset). The response includes nested invoiceLineItems so you can read the full invoice in one call.

List an invoice’s documents

Update an invoice

PUT /api/rest/invoices/{id} updates by Upwell ID. PUT /api/rest/invoices (without an ID) updates by sourceSystem + sourceSystemId in the body.

Adding or removing a shipment

invoiceShipments at create time (shown above) only covers the shipments you know about when the invoice is first created. To link or unlink a shipment from an existing invoice, use the standalone endpoints instead of trying to re-send invoiceShipments on a PUT:
Linking or unlinking a shipment triggers a background re-sync of that shipment’s documents onto (or off of) the invoice — the same “documents on a shipment are automatically visible on invoices linked to that shipment” behavior described above, kept in sync as the shipment list changes.

Invoice lifecycle

Invoices move through these statuses:
When a customer payment is applied to an invoice, update the invoice’s balance and status accordingly. Some TMS integrations manage this in Upwell; others update invoices from the TMS when payment is recorded there.

Webhook events

Subscribe to invoice events in the Upwell dashboard to get notified of status changes: An update.invoice.status.APPROVED trigger also exists but is support-enabled only. The webhook event catalog is the source of truth for trigger strings and dispatch rules; see Outbound webhooks for the delivery model, retries, and payload format.

What’s next

Customer payments

Record remittances applied to these invoices.

Statements & reminders

Automated follow-up on outstanding invoices.

Receivables management

The AR dashboard and reconciliation workflow.

Shipment documents

Attach supporting docs to shipments (shared with linked invoices).