Get API key
Authenticated — all requests require Authorization: Bearer mk_test_…Learn more
API ReferenceShipmentsCreate a shipment

Create a shipment

POST/api/v1/shipments idempotent

Re-quotes the selected service tier server-side, deducts the wallet in live mode (test mode skips), dispatches to the carrier, and returns the full shipment record with pricing snapshot + dispatch result. In live mode, dispatch.waybill_number is the carrier's waybill (e.g. Yun Express YT…) and dispatch.label_pdf_url its label PDF; with an mk_test_* key dispatch is skipped and dispatch is null — the example response shows a live-mode create. Requires Idempotency-Key. service_tier_id takes a Service Code (e.g. HKASTDGGSTCM) — list yours via GET /v1/service_tiers. Optional selected_surcharges opts into SIGNATURE / INSURANCE where eligible (check opt_in_availability on POST /v1/rates; eligibility is gated per destination and carrier product). Optional ioss_number (IM + 10 digits) overrides the account-level IOSS default for this shipment; EU destinations only.

Parameters

declared_currency
enum (HKD | USD)body
Declared-value currency for the whole shipment (items carry no currency of their own). "HKD": unit_price and unit_price_hkd are both HKD amounts; the server converts each item's HKD unit price to USD at the rate frozen when the order is placed and stores the shipment in USD (declared_currency reads back as "USD"), while billing still uses the HKD figures you sent (see declared_fx); if no rate can be resolved the whole shipment falls back to being stored in HKD and the order is never rejected for this reason. "USD": every item must use unit_price (not unit_price_hkd); in this mode an unresolvable rate returns 503 (FX_RATE_UNAVAILABLE). Omitted (changed in v1.20; previously always handled as "HKD"): decided by the price field the items use. If any item carries unit_price, the shipment is read as USD: unit_price is a USD amount, an item with no unit price is declared at 0, and an unresolvable rate returns 503. If no item carries unit_price (items use unit_price_hkd, or carry no unit price), the shipment is handled exactly as "HKD". Mixing unit_price and unit_price_hkd across items while declared_currency is omitted is rejected with 400 INVALID_FIELD. We recommend always sending declared_currency.
expected_discount_rule_id
stringbody
Discount rule_id returned by the selected /v1/rates option, or null when that option had no discount. When supplied, create rejects if the final quote differs.
expected_total_hkd
numberbody
total_hkd returned by the selected /v1/rates option. When supplied, create rejects if the final quote differs.
goods_category
stringbody
insured_amount
numberbody
Custom insured amount, in the shipment's declared currency — the same currency as unit_price (see declared_currency). Replaces the standard insurance pricing basis (0.7% × (freight + declared value), min HKD 9) with 0.7% × this amount converted to HKD at the frozen declared_fx rate (same minimum). Available only to accounts enrolled for custom insured amount, and only when the selected option's opt_in_availability INSURANCE entry (see POST /v1/rates) carries custom_insured_amount — today that means the cosmetics lane only. Requires "INSURANCE" in selected_surcharges (case-insensitive), else 400 INVALID_FIELD. Must be > 0 with at most 2 decimal places and at most USD 2500 (an HKD amount is converted at the frozen rate first) — any other value, or supplying it when the selected option does not support it, returns 400 INVALID_FIELD. On an HKD shipment for which no USD/HKD rate can be resolved, supplying it returns 503 FX_RATE_UNAVAILABLE.
ioss_number
stringbody
EU IOSS number (IM + 10 digits). Overrides the account-level default for this shipment; EU destinations only. With IOSS, EU VAT prepay is not charged and the number is forwarded to the carrier. The number must belong to your account — your own saved IOSS or a marketplace platform IOSS registered to you (contact support to add one); anything else returns 400 IOSS_NOT_OWNED.
items*
array<object>body
Required — at least one item (max 100). Every shipment must declare its contents; a request with no items is rejected with 400 before any order is created. unit_price / unit_price_hkd rules are unchanged (see each field).
metadata
objectbody
parcels*
array<object>body
payment_type
enum (prepaid | cod)body
Payment type. Only "prepaid" is currently available — "cod" (cash on delivery) returns 400 COD_NOT_AVAILABLE (1500034), with no quote, hold or shipment created.
recipient*
objectbody
reference_no
stringbody
Optional order reference of your own (e.g. your shop's order number, max 64 chars). Stored with the shipment, echoed in the create response, returned on list/detail reads, and usable as a list filter (GET /v1/shipments?reference_no=). Not required to be unique. Also printed on the carrier label when it is 6–50 characters of letters, digits and # & ( ) * + . : ; < = > ? [ ] ^ _ ` { | } - (not starting with = or +) and no other order already uses it; otherwise the label shows the iMile tracking number.
sales_platform_name
stringbody
Sales platform name (free text), required when recipient.country_code is JP — the carrier rejects Japan shipments without it. Optional for other destinations; when supplied it is still forwarded to the carrier. 1–50 characters.
selected_surcharges
array<string>body
Opt-in surcharge codes, e.g. ["SIGNATURE","INSURANCE"]. Eligibility is gated per destination and carrier product — check opt_in_availability on POST /v1/rates first; it is the authoritative source for which codes a given option accepts. Including "INSURANCE" when the final selected option's opt_in_availability marks it not selectable returns 400 INSURANCE_UNSUPPORTED — insurance is never silently dropped from an order.
sender
objectbody
service_tier_id*
stringbody
Service Code to book (e.g. HKASTDGGSTCM) — list the codes your account can use via GET /v1/service_tiers. The wire name service_tier_id is historical and kept for backwards compatibility.
tags
array<string>body
tax_number
stringbody
Destination tax registration number (e.g. Norway's VOEC number, or the recipient's RUT for Chile). Required for shipments to Norway (NO) unless voec_prepay is true, otherwise returns 400 TAX_NUMBER_REQUIRED. Required for shipments to Chile (CL) — the recipient's RUT — otherwise returns 400 CL_TAX_NUMBER_REQUIRED. Mutually exclusive with voec_prepay — sending both returns 400 VOEC_PREPAY_CONFLICT. 1–100 characters after trimming.
vat_prepay
booleanbody
Set true to have the carrier prepay destination VAT on your behalf (EU destinations only) instead of using an IOSS number. Mutually exclusive with ioss_number — sending both returns 400 IOSS_AND_PREPAY_CONFLICT. When true, the EU VAT prepay fee (declared value × destination VAT rate + 2% handling) is charged on the quote.
voec_prepay
booleanbody
Set true to have the carrier prepay Norway's VOEC VAT on your behalf, skipping tax_number entirely. Norway (NO) destinations only, on the standard-goods lane (service_tier_id HKASTDGGSTCM) or the cosmetics lane (HKASTDCSSTCM) — other lanes return 400 VOEC_PREPAY_UNSUPPORTED. Mutually exclusive with tax_number, ioss_number and vat_prepay — sending voec_prepay with any of them returns 400 VOEC_PREPAY_CONFLICT. Equivalent to including "NO_VOEC_PREPAY" in selected_surcharges (case-insensitive) — either form is honoured. When true, the fee is declared value × 27% on the standard-goods lane (plus HKD 3/shipment, and the carrier product silently switches to HK-ASS-PF) or declared value × 27% on the cosmetics lane (no switch, no per-shipment fee), charged on the quote.

Responses

Success body
{
  "status": 201,
  "message": "OK",
  "data": {
    "created_at": "2026-05-28T07:44:23.908Z",
    "dispatch": {
      "status": "dispatched",
      "carrier_code": "yunexpress",
      "waybill_number": "YT2614891234567890",
      "label_pdf_url": "https://example.com/labels/YT2614891234567890.pdf",
      "error": null
    },
    "id": "IM2605288471293048",
    "livemode": true,
    "parcels": [
      {
        "weight_kg": 0.5,
        "height_cm": 6,
        "length_cm": 22,
        "width_cm": 18
      }
    ],
    "pricing_snapshot": {
      "currency": "HKD",
      "freight_hkd": 58.5,
      "rate_table_code": "RT-HKASTDGGSTCM-US-v1",
      "rate_table_version": 1,
      "reg_fee_hkd": 36,
      "surcharges": [
        {
          "code": "FUEL",
          "amount_hkd": 4.7
        }
      ],
      "total_hkd": 99.2,
      "custom_insured_amount_hkd": 3900,
      "custom_insured_amount_usd": 500
    },
    "recipient": {
      "address": "1 Hacker Way",
      "city": "San Francisco",
      "contact_name": "John Doe",
      "country_code": "US",
      "district": "CA",
      "email": "ops@example.com",
      "phone": "+14155551234",
      "postal_code": "94025"
    },
    "reference_no": "PO-2026-0528-0017",
    "sender": null,
    "service_tier_id": "HKASTDGGSTCM",
    "status": "label_created",
    "tracking_number": "IM2605288471293048",
    "declared_currency": "USD",
    "declared_fx": {
      "fetched_at": "2026-05-28T07:44:23.908Z",
      "rate": 7.8454,
      "rate_type": "daily",
      "stale": false
    }
  }
}

Returned object

FieldTypeSample
statusnumber201
messagestringOK
dataobject{14 keys}