Arrange a pickup
/api/v1/pickups idempotentArrange a pickup for shipments returned by GET /v1/pickups/eligible-shipments. Send the same selection as the preview plus the preview_token it returned (valid 5 minutes). Requires Idempotency-Key and scope pickups:write. The first pickup arranged through the API switches the account to multiple pickup addresses (irreversible) and, when address is sent, saves that address. Fees belong to the whole address group of the day (or, for an arrangement made before the account switched, to the whole manifest): pickups arranged together share one fee, count it once per address_group_id / manifest_id, not per pickup. fee.state is the current state and the value to trust: for a new arrangement (fee.scope address_group) it is provisional until the day's last cut-off settles it and final afterwards; an older fee follows its own rule (manifest: final once its cut-off has locked or settled it; request: final from the start). Retries: the same Idempotency-Key with the same body returns the first response unchanged for 24 hours (including idempotent_replay: false). idempotent_replay: true appears when the same preview_token is sent again with a new Idempotency-Key and the booking already exists; that replay changes nothing and reports the current state, and it works after the 5-minute preview_token has expired. One exception: if the address sent inline was changed on file after the first booking, the retry is refused with 409 PICKUP_PREVIEW_STALE (1500107); that does not mean the booking failed, so keep the booking IDs from the first response and read the existing pickups with GET /v1/pickups/{pickup_id} instead of arranging again. pickup_slot is not part of the preview_token: it is checked again when the pickup is arranged, and a slot that is not open on the final date is rejected with PICKUP_INVALID_DATE_OR_SLOT instead of being replaced by another slot. After a new preview use a new Idempotency-Key.
Parameters
address_resolved_version; mutually exclusive with address.specific_date, forbidden for fastest.preview_token from POST /v1/pickups/preview (valid for 5 minutes).shipment_id values from GET /v1/pickups/eligible-shipments.outcome success (default) walks the pickup through submitted, driver_dispatched, picked_up and arrived_at_warehouse within about four minutes; failure makes the submission fail, so the pickup ends as failed. A failed test pickup keeps holding its shipments until it is cancelled, so cancel it within one hour of arranging it: after that it can no longer be cancelled and its test shipment stays held (create a new test shipment instead). Rejected with 400 for live keys.Responses
{ "status": 201, "message": "OK", "data": { "booking_intent_id": "3b9f0c1e-7a52-4d86-9c3e-0f4a1d2b6e75", "idempotent_replay": false, "manifest_id": null, "address_group_id": "6710a1b2c3d4e5f607182951", "address": { "address_id": "6710a1b2c3d4e5f607182940", "created": true }, "multi_pickup_enabled_now": false, "livemode": false, "pickups": [ { "id": "6710a1b2c3d4e5f607182960", "livemode": false, "simulated": true, "manifest_id": null, "address_group_id": "6710a1b2c3d4e5f607182951", "status": "requested", "destination": "yunexpress", "parcel_carriers": [ "yunexpress" ], "shipment_ids": [ "6710a1b2c3d4e5f607182931" ], "tracking_numbers": [ "IM2610190000000001" ], "pickup_date": "2026-10-21", "scheduled_pickup_date": "2026-10-21", "pickup_window": { "start": "13:00", "end": "17:00", "timezone": "Asia/Hong_Kong" }, "pickup_address": { "name": "Chan Tai Man", "phone": "+852 91234567", "email": "ops@example.com", "address_line": "Unit 1203, 12/F, Tower 2, Kowloon Commerce Centre, 51 Kwai Cheong Road, Kwai Chung" }, "carrier_tracking_number": null, "pickup_courier": null, "failure_reason": null, "fee": { "scope": "address_group", "state": "provisional", "estimated_hkd": 45, "charged_hkd": 0, "refunded_hkd": 0 }, "cancellation": { "allowed": true, "deadline": "2026-10-19T04:12:40.123Z", "reason_code": null }, "created_at": "2026-10-19T03:12:40.123Z", "updated_at": "2026-10-19T03:12:40.123Z" } ], "fee": { "state": "provisional", "free": false, "group_estimated_hkd": 45, "free_threshold_parcels": 5, "manifest_total_parcel_count": 1, "manifest_total_estimated_hkd": 45, "quota_conflicts": [] } } }
Returned object
| Field | Type | Sample |
|---|---|---|
| status | number | 201 |
| message | string | OK |
| data | object | {9 keys} |