Orders, Shipments, and Labels
How orders, shipments, rates, and labels relate, and which commands move each one along.
In Postsale, fulfilling work spans three related objects: orders, shipments, and labels. An order does not contain its label, and shipments are found through their parent orders. This article maps the domain the way the CLI uses it.
In this article, we will define orders, shipments, and labels, explain how they join, show how to list shipments from the CLI, and point you to work queue and empty-search behavior.
Before We Begin
This article assumes that:
- You have at least one order in the account (imported or manual)
postsale account envshows your environment and API host
What each object is
| Object | Role |
|---|---|
| Order | Commerce record: buyer, ship-to, line items, status, tags. Status names are defined by your account, not a global enum. |
| Shipment | Carrier-facing package plan for an order: packages, service, rates, tracking state. |
| Label | The purchased shipping document for a shipment. Void is a separate money-moving path. Reprint is not a purchase. |
How they connect
A shipment's reference field holds the parent order id when the shipment is created. That join is the backbone of CLI workflows.
Order ──creates/owns──► Shipment(s) ──purchase──► Label
id reference = order idNote
User-set fields like reference_1 / reference_2 / reference_3 on a shipment are different from this join reference.
Orders do not embed full shipments
You can filter orders with shipment-related conditions, but the order payload still does not carry complete shipment records. After you know order ids, fetch shipments explicitly.
How to get shipments from the CLI
There is no separate "shipment search universe" independent of orders. Supported paths:
-
postsale shipments list
Finds orders (natural language--query, structured JSON, or a default of orders that already have shipments), loads their shipments, and prints shipment-level rows withorder_idandorder_number. Pagination is at order grain. This command is CLI composition (not inschema --list). -
postsale shipments get --reference <order_id>
All shipments for one order. -
postsale shipments get [shipment_id]
One shipment by id (the id is optional when you pass--reference <order_id>instead). -
Agent tools
search_ordersthenlist_shipments_for_orders, orget_shipment.
A subtle backend detail
Shipments-by-order lookups are classified as read, but the backend may write during some of them: for unprocessed US shipments missing address validation, it can validate and save the address. They stay safe to call; the CLI just suppresses automatic retry on those paths.
Labels: purchase, void, reprint
| Action | Risk | CLI |
|---|---|---|
| Purchase | Money-moving | postsale labels purchase ... --yes / agent purchase_labels |
| Void | Money-moving | postsale labels void ... --yes / agent void_shipment |
| Reprint | Read | postsale labels reprint <shipment_id> (optional --output to download) |
Reprint re-fetches an existing label PDF URL. It does not charge again. Refunds after void depend on the carrier and backend state. The CLI does not guarantee a refund.
Finding work without silent empties
"What should I ship?" is a product question. In the agent, prefer get_work_queue over guessing status strings. Wrong statuses return zero orders that look like success.
When agent search returns zero matches, read _cli_meta.empty_result_context before concluding the account is empty. Full detail: Search and the work queue.
Try it
Here's how:
- Search recent orders:
postsale orders search --query "orders from last 7 days" --page-size 10- List shipments for a similar window:
postsale shipments list --query "orders from last 7 days" --page-size 10- Load every shipment for one order:
postsale shipments get --reference <order_id>- If a label already exists and you only need the PDF again:
postsale labels reprint <shipment_id>Success looks like JSON rows you can identify by order and shipment ids, without purchasing anything new.
Good to Know
- Web app shipping help (Dock, rate selector, void in the UI) is on postsale.com/help. The CLI paths above are the terminal equivalents for the same domain objects.
- Rate quotes can apply temporary dimension estimates. Do not reuse those estimates for real purchases. See Intent builders.
- Creating a shipment and purchasing a label are separate money-moving steps in the agent tool model.
PUTupdates of shipments, orders, and origin addresses are full replacements. A field you leave out is cleared, so read the object first and send it back whole. Carrier accounts are the exception in the CLI:carriers updatereads the current account and merges your keys onto it before calling the API (which itself replaces the whole record), so pass theidand only what you are changing (see carriers).- Bulk shipment updates touch only unprocessed shipments, skip the rest silently, and return no body. Re-read the shipments to confirm what changed.
- A processed USPS shipment carries
sender_addressandreturn_address: the label addresses copied from the USPS carrier account's settings at purchase time. Set them withpostsale carriers update(see carriers). - A shipment with
test_label: trueproduces watermarked, never-billed carrier test labels (USPS and UPS only). Store automation still runs for it. See Shipping, labels, and rates.POSTSALE_TEST_LABEL_MODEmakes the CLI stamp the flag on every shipment it creates and refuse to buy labels for any shipment without it — see the safety model. - Order fields a store's retention policy has redacted read as the literal string
[REDACTED]; the order'sredactedblock says which and why.
Additional Reading
On this page
Related