Skip to main content

Order-to-Label Workflow

The current integration scope uses an Order as the top-level fulfilment resource. An Order contains one or more Shipments. Shipment identifiers are used to request Rates and purchase a Label.

Order
└── Shipment
├── Rates
└── Label

Find an order​

GET/api/v1/orders GET/api/v1/orders/{orderId}

List Orders to find existing workflow state, or retrieve one Order by its ID. GET /api/v1/orders accepts search, sortByNewest, dateFrom, dateTo, statuses, sources, pageNumber, and pageSize as optional query parameters and returns a paged envelope — see Make Your First Request for a worked example. Full field-level schemas are in the API Reference.

Each listed Order reports where it came from in a source field, written by name: Manual for an Order created inside the Mailhub application, API for one created through this API, and Shopify for one imported from a connected store.

Filter the list by it with sources, which takes the numeric value of those names — 1 Manual, 2 API, 3 Shopify — and is repeated to match more than one. Listing only the Orders your integration did not create by hand looks like this:

GET /api/v1/orders?sources=2&sources=3

The filter takes numbers even though the response reports names, so ?sources=API is rejected with 400. Omit sources to return Orders from every source.

GET /api/v1/orders/{orderId} returns one Order in full. If you send X-SubAccount-Id, the Order must belong to that Sub-account — one belonging to a different Sub-account is reported as 404 Not Found. Omit the header to look up Orders across the authenticated Account. See Work with Sub-accounts.

Standard Order workflow​

The workflow is a chain of calls in which each response hands the next request an identifier:

  1. Create an Order — retain the returned orderId and every shipmentId.
  2. Get Rates for a shipmentId. Your application selects one Rate and keeps its id, which travels back as a nested rate object.
  3. Buy a Label for that Shipment. A successful response is the Shipment, with the Label nested inside it: retain data.postageLabel.id as your labelId. The response is not a standalone Label object and carries no top-level labelId.
  4. Download the Label using that labelId.

Create an Order with Rates is an alternative to the first two calls: it creates the Order and returns its initial Rates in one response. The optional Order-management calls — read, list, and update status — sit alongside the chain rather than inside it. If a purchased Label has to be reversed, use Cancel a Label rather than a second purchase.

Both Label steps can answer 202, and the two mean different things:

  • Label purchase 202 — the purchase is accepted and still running. It carries no Retry-After and there is no operation-status endpoint to poll: observe the outcome by reading the Order, or repeat the same purchase request within your own bounded budget. See Recover a Label Purchase After 202.
  • Label download 202 — the Label file is still being generated. This one does carry a Retry-After header: wait the number of seconds it gives, then retry the same download.
  1. Authenticate

    Obtain an access token before making protected integration requests.

  2. Create an Order

    Create an Order and read back its Order and Shipment identifiers.

  3. Request Rates

    Request available Rate options for the Shipment — this works regardless of the Order’s status.

  4. Select a Rate

    Keep the selected Rate identifier for label purchase.

  5. Purchase a Label

    Purchase a Label for the Shipment using the selected Rate. The Order automatically becomes LabelCreated.

  6. Download the Label

    Save or stream the non-JSON file response securely.

  7. Mark the Order Fulfilled

    Update the Order once the shipment has been handed to the carrier.

Fulfilled is enforced: it is only reachable from LabelCreated, so mark it only after a Label has been purchased (see Update Order Status for the full supported-transition table).

Optional cancellation branch​

If a purchased Label needs to be cancelled, follow Cancel a Label. Cancellation is an explicit workflow branch, not a required final step, and returns the Order to Packed.

Alternative: create with rates in one call​

The workflow above starts with standard Order creation. For one Order, Create an Order with Rates combines creation and initial rating in one request. It remains one Order per request and does not change the separate Label workflow.

Guides​

Working with USPS? See USPS with Mailhub for carrier context on the same sequence.