API reference

Create an order

Hand one or more packages to Starmile in a single order. The order is your grouping (order_id); each parcel is a hub package with its own Starmile tracking number, and each parcel lists its products. Creating the order starts a logistics flow per parcel; the 201 returns the order with its parcels, and later status changes appear in your status pool.

Authentication is required (see Authentication). The order is created for the partner the credential belongs to, in the warehouse the credential is bound to — you never send those in the body.

Every order names a service_id — the id of a Service returned by GET /api/v1/services (read from your services & rates). The Service carries everything the order needs: the underlying flow, the corridor (origin & destination), and the delivery type— so you don’t send origin/destination.

You do not send a rate. Starmile resolves the applicable rate automatically and raises the invoice when the parcel reaches the status that rate is configured to bill on.

The delivery destination is bound to the service’s type: a Home Delivery service expects a parent_region + region, a Pudo Delivery service a pudo_id; Clearance and Cross Docking need no end-customer destination. A missing or invalid destination is rejected 422 with a message.

For Home Delivery you address the destination by your own reference: your parent region id/code in parent_region (e.g. "1") plus your leaf region id/code in region (e.g. "2"). Starmile maps that pair, per partner, to one of its regions — so your ids never need to match ours, and a leaf name that repeats across parents is disambiguated by the parent. The resolved region carries the delivery’s pricing tier.

If your reference is not mapped yet, the order is still accepted — it is not rejected. The response carries region_status: "mapped" when the region resolved, or "pending_mapping" when it did not. A pending_mapping order is queued for an operator to map your region in Starmile; once mapped, the waiting order is resolved automatically — you do not resend it. For a PUDO / locker / clearance service (no home region) region_status is "not_applicable".

Each entry in parcels[] is a physical package handled in the hub. item_id is your per-package reference — optional; when sent it is echoed back on the parcel as partner_tracking, and when omitted partner_tracking is left empty. merchant_trackingis the code on the sticker (also optional — set it later via the update endpoint, or omit it and Starmile fills it with the parcel’s own tracking number). Weights and dimensions are records-only; the hub re-measures (DWS) on arrival.

Your own references must be unique — your order_id, each parcel’s item_id, and each merchant_tracking. Reusing one that already exists (or repeating an item_id / merchant_tracking across parcels in the same order) is rejected 422 with a message, so re-sending an order never creates a duplicate.

One Starmile tracking per parcel

The order gets one Starmile tracking number — returned as order_id on create — and each parcel gets its own internally. You address a parcel by your own merchant_tracking (barcode); operators scan by that or the Starmile tracking.

Create an order

POST/api/v1/orders

Body — order

service_idintegerrequired
The id of a Service from GET /api/v1/services (the Service entity — the flow is resolved from it). Must be published for your partner in this warehouse.
order_idstringrequired
Your reference for the order (max 255).
gov_idstringoptional
Recipient government ID — the AZ FIN or a foreign passport number — used for the customs declaration.
customer_namestringoptional
Recipient name (max 255).
customer_phonestringoptional
Recipient phone (max 64).
customer_emailstringoptional
Recipient email.
pudo_idintegeroptional
Required for a pudo-channel service: the id of a PUDO point in the destination country. The delivery channel (home / pudo / locker) is a property of the chosen service, not a field you send.
parent_regionstringoptional
Required for a Home Delivery service: YOUR own parent region id/code (e.g. "1"). With region, it forms the per-partner mapping key an operator maps to one of Starmile's regions; the parent disambiguates a leaf that repeats across parents.
regionstringoptional
Required for a Home Delivery service: YOUR own leaf region id/code (e.g. "2"). Resolved map-only, per partner, to one of Starmile's regions (no name/id fallback). An unmapped reference does NOT reject the order — it is accepted with region_status "pending_mapping" and resolved once an operator maps it. The resolved region carries the delivery's pricing tier.
address_firststringoptional
Address line 1 (home delivery).
address_secondstringoptional
Address line 2 (home delivery).
zipstringoptional
Postal / zip code (max 32).
notesstringoptional
Delivery notes for the courier (max 1000).
shipping_costnumberoptional
Optional. What you charge to ship this order, in the declared-value currency; it becomes the customs transport cost. Range 0–1,000,000. A zero (or omitted) shipping cost is treated as none — the order stores no value and customs sends a minimum at declaration time.
consolidation_requiredbooleanoptional
Optional. Ask to consolidate the order's parcels. The chosen service must enable consolidation — otherwise the order is rejected 422 ("Consolidation is not enabled for this service.").

Body — parcels[]

parcels[].item_idstringrequired
Your per-package reference (max 255). Unique within the order. Echoed back on the parcel as partner_tracking.
parcels[].merchant_trackingstringoptional
The code on the physical sticker (optional; settable later).
parcels[].package_typestringoptional
One of: fragile, breakable, liquid.
parcels[].weight_gramsintegeroptional
Declared gross weight (records-only; DWS re-measures).
parcels[].length_mm / width_mm / height_mmintegeroptional
Declared dimensions in mm (records-only).

Body — parcels[].products[]

products[].namestringrequired
Product name (max 255).
products[].hs_codestringoptional
Harmonised System code (max 32).
products[].declared_valuenumberoptional
Declared customs value of the product.
products[].currencystringoptional
ISO-4217 currency code (3 letters).
products[].quantityintegeroptional
Quantity (default 1).
products[].weight_gramsintegeroptional
Product weight in grams.

Response (201)

data.order_idstringoptional
The created order's Starmile tracking number. Use it as the order_id on the status and management endpoints.
data.region_statusstringoptional
Home Delivery region resolution: "mapped" (resolved), "pending_mapping" (accepted, awaiting an operator mapping — resolves automatically, do not resend), or "not_applicable" (PUDO / locker / clearance — no home region).
data.items[]arrayoptional
One entry per parcel: your item_id (as sent, or null if omitted) and parcel_id — our parcel's Starmile tracking number.
curl -X POST https://api.starmile.io/api/v1/orders \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "service_id": 4,
    "order_id": "PO-10294",
    "gov_id": "5AB12C3",
    "customer_name": "Aysel M.",
    "customer_phone": "+994500000000",
    "parent_region": "1",
    "region": "2",
    "address_first": "Nizami 10",
    "address_second": "Apt 4",
    "zip": "AZ1000",
    "notes": "Ring twice",
    "shipping_cost": 9.50,
    "parcels": [
      {
        "item_id": "PKG-1",
        "merchant_tracking": "CN773300012345",
        "package_type": "fragile",
        "weight_grams": 1400,
        "products": [
          { "name": "Sneakers", "hs_code": "640411", "declared_value": 120.00, "currency": "USD", "quantity": 1 }
        ]
      }
    ]
  }'

Update a parcel

Change a parcel’s details while the order is still at its flow’s first step — most often to set the merchant_tracking (sticker code) once you have it. Partial: only the fields you send change; products, when sent, replaces the whole list. Once the order has moved past its first step (for example the parcel has been received at the hub) the update is rejected 409. Requires the orders:update scope. The path uses your own references: order_idthen the parcel’s item_id.

Update a parcel

PATCH/api/v1/orders/{order_id}/parcels/{item_id}

Body (all optional; partial update)

merchant_trackingstringoptional
The physical sticker code.
package_typestringoptional
One of: fragile, breakable, liquid.
weight_gramsintegeroptional
Declared gross weight (records-only).
length_mm / width_mm / height_mmintegeroptional
Declared dimensions in mm.
productsarrayoptional
Replaces the parcel's full product list (same shape as create).
curl -X PATCH https://api.starmile.io/api/v1/orders/PO-10294/parcels/PKG-1 \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "merchant_tracking": "CN773300099999",
    "package_type": "liquid",
    "products": [
      { "name": "Olive oil 1L", "hs_code": "150910", "declared_value": 18.0, "currency": "USD", "quantity": 2 }
    ]
  }'

Cancel an order

Cancel an order while it is still at its flow’s first step — before any of its packages have moved past it (e.g. been received or handed to a carrier). Once any parcel has advanced past the first step the cancel is rejected 409. Idempotent for an already-cancelled order. Requires the orders:cancel scope.

Cancel an order

POST/api/v1/orders/{order_id}/cancel

Body

reasonstringoptional
Optional free-text cancellation reason.
curl -X POST https://api.starmile.io/api/v1/orders/PO-10294/cancel \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Content-Type: application/json' \
  -d '{ "reason": "customer changed their mind" }'