Get API key
Authenticated — all requests require Authorization: Bearer mk_test_…Learn more
API ReferencePickupsDeclare a self drop-off

Declare a self drop-off

POST/api/v1/pickups/self-dropoffs idempotent

Declare that you will take shipments to the carrier warehouse yourself instead of arranging a pickup. Requires Idempotency-Key and scope pickups:write. A declaration is free: no fee is charged and nothing moves on the wallet. Its shipments are put on hold: they cannot be arranged for pickup and POST /v1/shipments/{shipment_id}/cancel refuses them with 409 SHIPMENT_HAS_ACTIVE_PICKUP (1500116) while the record is declared or arrived_at_warehouse; only a cancelled record, released by our operations team, frees them. A shipment whose order type does not support self drop-off is refused with 409 ORDER_TYPE_OPERATION_UNSUPPORTED (1500047). Hong Kong origin only. The API accepts only shipments sent from Hong Kong (a shipment whose service is a Hong Kong-origin service); Chinese-origin shipments cannot be declared through the API. The request is checked as a whole: if any one shipment is Chinese-origin, or its origin cannot be determined, the whole request is refused with 400 SELF_DROPOFF_ORIGIN_NOT_SUPPORTED (1500117, data.reason_code origin_not_supported or origin_undetermined) and nothing is created for any of the shipments, so send Hong Kong-origin shipments in their own request. Take the shipment ids from GET /v1/pickups/eligible-shipments (shipment_id, not the tracking number). One declaration creates one record per destination warehouse (records). dropoff_date must be one of the dates in allowed_dates_by_warehouse_key of GET /v1/pickups/self-dropoffs/config; when the shipments go to more than one warehouse the date must be allowed for every one of them (the dates the warehouses have in common), otherwise the request is refused with 400 PICKUP_INVALID_DATE_OR_SLOT (1500111, reason invalid_dropoff_date). The Globavend pre-alert email is sent as soon as the declaration is confirmed, for a record whose warehouse_key is globavend. A failure to send it does not fail the declaration; the system retries it. The email recipients are fixed by us. There is no way to cancel, change or delete a declaration through the API: POST /v1/pickups/{pickup_id}/cancel does not apply to a self drop-off (the id answers 404) and the scope pickups:cancel has no effect on it. If a declaration must be released, contact customer service. Retries are protected twice. For 24 hours the same Idempotency-Key with the same body returns the first response unchanged (idempotent: false included); the same key with a different body is 409 IDEMPOTENCY_KEY_REUSED. After 24 hours the key itself is no longer remembered, but the declaration still is: sending the same Idempotency-Key with the same shipments from the same API key returns the original records with idempotent: true, in their current state (the status may have moved on), and creates nothing, even if the new request carries a different dropoff_date. The same key with a different set of shipments is 409 IDEMPOTENCY_KEY_REUSED. A new key for shipments that are already declared is 409 PICKUP_SHIPMENTS_NOT_BOOKABLE (1500106). Use a new key for every new declaration. Test keys (mk_test_) run on the simulator: nothing is sent to any carrier, no email is sent and nothing is stored with live data; the records have livemode: false and simulated: true, and only test shipments (created with a test key) can be declared. About 60 seconds after the declaration (within about a minute of that) a record moves from declared to arrived_at_warehouse. Send simulation: {"outcome": "cancelled"} (test keys only; a live key gets 400 PICKUP_INVALID_REQUEST, reason simulation_not_allowed) to make it move to cancelled instead, as if our operations team had cancelled it. Reading a record never advances it. While a test record is declared or arrived_at_warehouse it holds its test shipments; cancelled releases them. Status changes are delivered as the webhook events self_dropoff.declared, self_dropoff.arrived_at_warehouse and self_dropoff.cancelled (see POST /v1/webhooks). Only transitions after pickup events were switched on are published; earlier history is not sent. Until the self drop-off API is switched on for your environment the config and declaration endpoints answer 503 PICKUP_FEATURE_DISABLED (1500103) with data.reason_code public_api_self_dropoff_disabled; with a live key a declaration also needs the web self drop-off feature (reason self_dropoff_disabled). Listing and reading records only need the pickup API master switch (reason public_api_pickups_disabled).

Parameters

customer_tracking_numbers
objectbody
Your own tracking number per destination warehouse (optional, up to 60 characters: letters, digits, spaces and . _ / -, starting with a letter or digit).
dropoff_date*
stringbody
A real calendar date, YYYY-MM-DD (Hong Kong), one of the dates from GET /v1/pickups/self-dropoffs/config.
remark
stringbody
Free-text note for operations (up to 200 characters).
shipment_ids*
array<string>body
1–300 shipment_id values (24 lowercase hex characters, no duplicates). Shipments must be Hong Kong-origin and not yet picked up or declared.
simulation
objectbody
Test keys only: steers the sandbox simulator. arrived_at_warehouse (default) moves the declaration to arrived_at_warehouse after about a minute; cancelled simulates an operations-side cancellation instead. Rejected with 400 for live keys.

Responses

Success body
{
  "status": 201,
  "message": "OK",
  "data": {
    "idempotent": false,
    "records": [
      {
        "self_dropoff_id": "6710a1b2c3d4e5f607182971",
        "status": "declared",
        "shipment_ids": [
          "6710a1b2c3d4e5f607182932"
        ],
        "dropoff_date": "2026-10-30",
        "destination_mode": "per_carrier",
        "warehouse_key": "yunexpress",
        "warehouse": {
          "code": null,
          "name": "YunExpress Hong Kong warehouse",
          "mobile_prefix": "+852",
          "mobile": "55550100",
          "address": "Warehouse 3, 18 Example Road, Kwai Chung, New Territories, Hong Kong"
        },
        "customer_tracking_number": null,
        "remark": "Dropped off by our courier in the afternoon",
        "created_at": "2026-10-28T03:12:40.123Z",
        "updated_at": "2026-10-28T03:12:40.123Z",
        "arrived_at": null,
        "cancelled_at": null,
        "livemode": false,
        "simulated": true
      },
      {
        "self_dropoff_id": "6710a1b2c3d4e5f607182972",
        "status": "declared",
        "shipment_ids": [
          "6710a1b2c3d4e5f607182933"
        ],
        "dropoff_date": "2026-10-30",
        "destination_mode": "per_carrier",
        "warehouse_key": "globavend",
        "warehouse": {
          "code": null,
          "name": "Globavend Hong Kong warehouse",
          "mobile_prefix": "+852",
          "mobile": "55550200",
          "address": "Unit 5, 9/F, 33 Sample Street, Tsuen Wan, New Territories, Hong Kong"
        },
        "customer_tracking_number": "MY-GV-0001",
        "remark": "Dropped off by our courier in the afternoon",
        "created_at": "2026-10-28T03:12:40.123Z",
        "updated_at": "2026-10-28T03:12:40.123Z",
        "arrived_at": null,
        "cancelled_at": null,
        "livemode": false,
        "simulated": true
      }
    ]
  }
}

Returned object

FieldTypeSample
statusnumber201
messagestringOK
dataobject{2 keys}