Skip to main content

Core concepts & data model

Upwell sits between your TMS and your money. It has two jobs:
  • Accounts receivable (AR) — money in. Getting your customers (shippers) to pay you, quickly.
  • Accounts payable (AP) — money out. Making sure what you pay your carriers is accurate.
Almost everything in the product is one of a small set of objects. Learn these once and the rest of the docs read easily.

The objects

Two more terms come up constantly but aren’t objects you create directly — Upwell derives them:
  • Exception — a flagged audit finding on an invoice: a mismatch, a missing document, or a failed match. Exceptions arise on both sides — carrier invoices (AP) and customer invoices (AR). See Exceptions.
  • Approval request — a pending decision on a carrier invoice, awaiting sign-off before Upwell proceeds. See how approvals work and responding to an approval request.

How they connect

A shipment ties the two sides together: the same load you invoice a customer for (AR) is the load a carrier bills you for (AP).

Addresses

Addresses are the one object people most often model wrong, so it’s worth being explicit: an address is not a globally shared, deduplicated entity the way a customer or a carrier is. A customer (cus_) or carrier (car_) represents a business entity that integrations generally retain and reference by ID. Addresses do not represent a shared physical-place identity in that way. An address (addr_) is a typed snapshot associated with the record that uses it:
  • Each address carries a type describing the role it plays, and it is required — there’s no default. Two types are load-bearing and must be exact: CUSTOMER_BILLING (what the invoice bill-to block and delivery routing read) and COMPANY_ADDRESS (the only type a company page will display). SHIPMENT_PICKUP and SHIPMENT_CONSIGNEE fill a shipment’s origin/destination slots. CARRIER, CARRIER_BILLING, CONTACT and STOP are descriptive. ADDRESS_BOOK is inert — nothing reads it, so it is not a safe generic default. The same party can hold several rows (a customer’s billing address and its dock address are two).
  • Each address describes a particular use — for example, a shipment pickup or consignee, a customer billing location, a company address, or a contact address. It is created in that context, not looked up from a shared pool.
  • There is no automatic dedup at the address level. The same physical location on two different shipments is two separate addr_ rows. Two customers at the same building have two address records. This is expected — and it’s usually what trips up integrations that assume one ID per real-world place.
  • Addresses have no sourceSystem / sourceSystemId pair — unlike every other resource in this table. There is no upsert-by-external-key for an address; you must store and track the Upwell addr_ id yourself for every address you create.
If you’re keeping your own records straight against Upwell, key off the parent object and the address type (e.g. “the SHIPMENT_CONSIGNEE address on shipment shi_…”), not off an assumption that a given physical address always maps to one stable address ID. It doesn’t.
For the mechanics — creating a record with its address, adding one later, updating it, and which direction the link runs for each parent type — see Working with addresses.

Canonical addresses — where dedup actually happens

The “one global ID per real place, with a key to prevent duplicates” idea does exist in Upwell — just one layer down, and not as an object you create or reference directly. A canonical address (can_) is a normalized, cross-tenant record keyed by a verification key from our address-verification provider (Smarty). It’s upserted on that key, so repeated matches for the same verified US address resolve to the same canonical record — that’s the deduplication. An addr_ record can carry a canonicalAddressId pointing at its canonical match.
In practice, don’t expect to see this populated. Assume canonicalAddressId is unset on any address you create: it is effectively never set on CARRIER, CARRIER_BILLING, CUSTOMER_BILLING, or any type besides SHIPMENT_PICKUP/SHIPMENT_CONSIGNEE — and not reliably even there. The real driver is the customer location codes feature (named pickup/delivery locations a customer configures): almost every canonicalized address traces back to a location-code match, not general address processing. Canonicalization is a byproduct of that narrow, opt-in feature, not something that runs against the addresses a typical integration creates.
Canonical addresses are an internal normalization and matching aid, not a first-class API resource. The API may expose an address’s canonicalAddressId, but integrations should treat it as system-maintained metadata rather than a stable identifier they manage themselves. Matching is US-only and best-effort — a non-US or unverifiable address simply has no canonical match.

Four pairs people mix up

  • An address (addr_) is a typed, per-owner snapshot — the pickup on this shipment, the billing address on that customer. The same physical place used in two spots is two separate address rows; there’s no global dedup at this level.
  • A canonical address (can_) is the normalized, cross-tenant record keyed by an address-verification key — this is the deduplicated “one ID per verified place.” It’s an internal matching aid; integrations should treat canonicalAddressId as system-maintained metadata. See Addresses.
Both are on the payables side, and this is the one that trips people up most.
  • A bill (bil_) is what your TMS says you should owe a carrier — the expected amount.
  • A carrier invoice (cari_) is what the carrier actually sent you — the received amount.
Upwell’s core AP job is auditing the carrier invoice against the bill. When they don’t agree, that difference becomes an exception.
Same word, opposite directions of money:
  • An invoice (inv_) is you billing your customer — accounts receivable, money in.
  • A carrier invoice (cari_) is a carrier billing you — accounts payable, money out.
Throughout the docs and API, an unqualified “invoice” always means the customer/AR invoice.
  • Your customer (cus_) is the shipper — they pay you (AR).
  • Your carrier (car_) is who you hire to move the freight — you pay them (AP).

How money moves

1

Receivables — collecting from customers (money in)

A shipment produces an invoice to the customer. When they pay, that arrives as a customer payment whose line items apply to the invoices it covers. See Recording customer payments and Accounts receivable management.
2

Payables — paying carriers accurately (money out)

Your TMS provides a bill — what you expect to owe the carrier. The carrier sends a carrier invoice; Upwell audits it against the bill and flags exceptions for any mismatch. Once it’s approved, a bill payment settles it, its line items applying to the bill(s) it covers — the same pattern as a customer payment on the AR side. See Carrier invoice audit and Submitting carrier invoices via API.
This page defines the core money-flow objects; the guides go deeper on each. For every other term — freight jargon (accessorial, lumper, SCAC, LTL), AP/AR terms (aging, remit-to, factoring), and other objects (stop, rule, document reference specification) — see the glossary. For the exact fields and endpoints, the API Reference is generated from the API schema.