# 運單事件代碼

根據目前環境的 `tracking` 字典表（有哪些狀態碼、客戶是否可見）、TrackingEvent 鍵與在地化 `tracking.*` 描述文案在 https://api.superlabel.ca/api/documentation/tracking-events?lang=cht 即時產生，始終與本環境資料庫一致。

## 事件側別，不是訂單類型

本字典**不是**訂單類型列表。同一筆訂單可以同時產生取件側與配送側事件——例如帶取件環節的配送、點對點（雙段）、多段轉運、倉配交接等。即時配送使用單獨字典（本頁不列）。每條運單事件會打上**側別**（取件側或配送側），用於匹配對應狀態的描述文案與可見性。數值 `status_id` 與穩定 `key` 對應 API / Webhook 中的 `tracking_event_status_id` / `tracking_event_key`；請基於這些欄位（以及需要時看側別）做分支，不要用訂單類型，也不要依賴在地化描述文字。

## 客戶可見性（`tracking.visible`）

公開運單頁與公開運單 API 僅展示字典列 `tracking.visible = 1` 的事件，並按狀態碼**與**事件側別（與運單事件上標記的側別一致）關聯。下方標記為 **否** 的狀態仍存在於系統中（Webhook、操作歷史、內部工具），但不會出現在客戶可見時間線。可見性從本部署的 `tracking` 表即時讀取。

## 配送側事件

運單事件落在行程**配送側**（派送 / 末端段）時使用的狀態。適用於純配送、點對點的配送段、先取後派、多段轉運等，**不限於**「純配送訂單」。**客戶可見** 為本側該狀態的 `tracking.visible`。

| status_id | key | otep | otep phase | 客戶可見 | description |
|---|---|---|---|---|---|
| 100 | `information_submitted` | `information_submitted` | `pre_shipment` | 是 | 您的寄件資訊已提交。 |
| 110 | `booking_confirmed` | `booking_confirmed` | `pre_shipment` | 是 | 您的寄件已確認。 |
| 120 | `awaiting_pickup` | `awaiting_pickup` | `pre_shipment` | 是 | 您的包裹正在等待攬收。 |
| 200 | `pushed_successful` | — | — | 否 | 您的訂單已提交路線規劃。 |
| 201 | `pushed_failed` | — | — | 否 | 您的訂單未能提交路線規劃，將重試或重新安排。 |
| 300 | `received` | `received` | `inbound` | 是 | 您的包裹已安全抵達 {warehouse_name}。 |
| 301 | `arrival_scan` | `arrival_scan` | `inbound` | 是 | 您的包裹已完成攬收，並送達 {warehouse_name}。 |
| 400 | `planned` | `in_transit` | `transit` | 否 | 您的包裹已裝車，準備派送。 |
| 401 | `removed_from_route` | `removed_from_route` | `exception` | 否 | 您的配送計畫即將重新安排，請稍待更新通知。 |
| 402 | `route_cancelled` | `route_cancelled` | `exception` | 否 | 您的配送狀態即將更新，請稍候。 |
| 430 | `in_transit` | `in_transit` | `transit` | 是 | 您的包裹正在運輸途中。 |
| 431 | `on_hold` | `in_transit` | `transit` | 是 | 您的包裹暫時滯留,恢復運輸後我們會第一時間更新。 |
| 432 | `customs_clearance` | `in_transit` | `transit` | 是 | 您的包裹正在清關中。 |
| 433 | `loaded` | `package_outbound` | `transit` | 是 | 您的包裹已裝車,即將發出。 |
| 434 | `collection_on_hold` | `awaiting_pickup` | `pre_shipment` | 是 | 您的包裹攬收暫時受阻,我們會盡快更新。 |
| 435 | `facility_received` | `in_transit` | `transit` | 是 | 您的包裹已被轉運站點接收。 |
| 436 | `arrived_at_facility` | `in_transit` | `transit` | 是 | 您的包裹已到達轉運站點。 |
| 450 | `start_delivery` | `out_for_delivery` | `out_for_delivery` | 是 | 您的包裹正在派送途中。 |
| 470 | `at_device` | `awaiting_pickup` | `pre_shipment` | 是 | 您的包裹已放入自助櫃，等待您取件。 |
| 471 | `device_picked_up` | `delivered` | `delivered` | 是 | 您的包裹已從自助櫃取出。 |
| 472 | `device_expired` | `awaiting_pickup` | `pre_shipment` | 是 | 您的包裹未在截止時間前取出，仍在自助櫃中。 |
| 473 | `device_removed` | `received` | `inbound` | 是 | 您的包裹已由工作人員從自助櫃中取出。 |
| 500 | `deliver_success` | `delivered` | `delivered` | 是 | 您的包裹已成功送達，感謝您的使用！ |
| 501 | `need_rescheduled` | `delivery_rescheduled` | `exception` | 是 | 很抱歉，我們未能成功派送您的包裹。 |
| 502 | `redelivered_later` | `delivery_rescheduled` | `exception` | 是 | 很抱歉，我們未能成功派送您的包裹。 |
| 503 | `not_delivered` | `delivery_failed` | `exception` | 是 | 您的配送過程中出現問題，請聯繫客服解決。 |
| 504 | `partial_deliver_success` | — | — | 是 | 本包裹已送達，其餘包裹仍在派送途中。 |
| 510 | `pickuped` | `picked_up` | `pickup` | 是 | 包裹已被我們的快遞員成功取走。 |
| 800 | `package_outbound` | `package_outbound` | `transit` | 是 | 您的包裹已從 {warehouse_name} 出庫。 |

## 取件側事件

運單事件落在行程**取件側**（攬收 / 取件段）時使用的狀態。適用於純取件、點對點的取件段、先取後派、多段轉運等，**不限於**「純取件訂單」。**客戶可見** 為本側該狀態的 `tracking.visible`。

| status_id | key | otep | otep phase | 客戶可見 | description |
|---|---|---|---|---|---|
| 100 | `information_submitted` | `information_submitted` | `pre_shipment` | 是 | 您的寄件請求已成功提交。 |
| 110 | `booking_confirmed` | `booking_confirmed` | `pre_shipment` | 是 | 您的取件請求已確認。 |
| 120 | `awaiting_pickup` | `awaiting_pickup` | `pre_shipment` | 是 | 您的包裹正在等待攬收。 |
| 200 | `pushed_successful` | — | — | 否 | 您的取件訂單已提交路線規劃。 |
| 201 | `pushed_failed` | — | — | 否 | 您的取件訂單未能提交路線規劃，將重試或重新安排。 |
| 300 | `received` | `received` | `inbound` | 是 | 您的包裹已成功入庫。 |
| 301 | `arrival_scan` | `arrival_scan` | `inbound` | 是 | Order a-scan |
| 400 | `planned` | `in_transit` | `transit` | 否 | 您的包裹正在處理中。 |
| 401 | `removed_from_route` | `removed_from_route` | `exception` | 否 | 您的取件計畫即將重新安排，請等待通知。 |
| 402 | `route_cancelled` | `route_cancelled` | `exception` | 否 | 您的取件狀態即將更新，請稍候。 |
| 430 | `in_transit` | `in_transit` | `transit` | 是 | 您的包裹正在運輸途中。 |
| 431 | `on_hold` | `in_transit` | `transit` | 是 | 您的包裹暫時滯留,恢復運輸後我們會第一時間更新。 |
| 432 | `customs_clearance` | `in_transit` | `transit` | 是 | 您的包裹正在清關中。 |
| 433 | `loaded` | `package_outbound` | `transit` | 是 | 您的包裹已裝車,即將發出。 |
| 434 | `collection_on_hold` | `awaiting_pickup` | `pre_shipment` | 是 | 您的包裹攬收暫時受阻,我們會盡快更新。 |
| 435 | `facility_received` | `in_transit` | `transit` | 是 | 您的包裹已被轉運站點接收。 |
| 436 | `arrived_at_facility` | `in_transit` | `transit` | 是 | 您的包裹已到達轉運站點。 |
| 450 | `start_delivery` | `out_for_delivery` | `out_for_delivery` | 是 | 快遞員正在前往取件，請準備好您的包裹。 |
| 470 | `at_device` | `awaiting_pickup` | `pre_shipment` | 是 | 您的包裹已放入自助櫃，等待您取件。 |
| 471 | `device_picked_up` | `delivered` | `delivered` | 是 | 您的包裹已從自助櫃取出。 |
| 472 | `device_expired` | `awaiting_pickup` | `pre_shipment` | 是 | 您的包裹未在截止時間前取出，仍在自助櫃中。 |
| 473 | `device_removed` | `received` | `inbound` | 是 | 您的包裹已由工作人員從自助櫃中取出。 |
| 500 | `deliver_success` | `delivered` | `delivered` | 是 | 您的包裹已成功取件。 |
| 501 | `need_rescheduled` | `delivery_rescheduled` | `exception` | 是 | 您的取件已重新安排，我們稍後將通知您新的取件時間。 |
| 502 | `redelivered_later` | `delivery_rescheduled` | `exception` | 是 | 您的取件已重新安排，我們稍後將通知您新的取件時間。 |
| 503 | `not_delivered` | `delivery_failed` | `exception` | 是 | 您的包裹出現問題，請聯繫客服解決。 |
| 504 | `partial_deliver_success` | — | — | 是 | 本包裹已取件，其餘包裹仍在等待取件。 |
| 510 | `pickuped` | `picked_up` | `pickup` | 是 | 您的包裹已成功取件。 |
| 800 | `package_outbound` | `package_outbound` | `transit` | 是 | 您的包裹已從 {warehouse_name} 出庫。 |

**otep** / **otep phase** 欄由 `OTEPStatusInput::FROM_TRACKING_EVENT` 與 `PHASES` 即時產生——與公開運單 API 在事件上寫入的 `otep_status` 同源。破折號（—）表示該內部狀態在 parcel 設定檔中無對應 OTEP 代碼（例如路線推送 200/201）；事件仍會落庫，且在 `visible = 1` 時仍可能對客戶可見。

## 用公開運單 API 自建追蹤頁

使用**公開運單查詢 API** 即可在自己的網站或 App 上做品牌化追蹤頁——無需登入、無需 API Token。同一介面支撐內建追蹤頁與 GraphQL `trackingPublic`。請結合本頁的狀態字典（代碼、可見性、OTEP）與下方流轉規律使用。

### 1. 呼叫公開介面

依運單號一次 GET 即可。可查 Superroute 運單號、外部運單號，以及部分未綁定第三方服務商的三方運單號。

```
GET https://api.superlabel.ca/api/v1/tracking/{tracking_number}
```

- No authentication — public, rate-limited with the rest of the API.
- Path parameter: the Superroute tracking number, external tracking number, or (when applicable) third-party tracking number without a third-party provider id.
- HTTP **200** with `"result": true` when found; **404** with `"result": false` when not found or the order is cancelled.

### 2. 選擇描述語言

事件的 `description` 文案隨請求語言變化，透過 `Accept-Language` 請求頭設定。可傳送專案語言碼如 `en`、`chs`、`cht`、`de` 等，或常見別名如 `zh-TW` → 繁體中文。未提供或無法識別時使用預設語言。

```
Accept-Language: chs
Accept-Language: zh-CN
Accept-Language: de
```

### 3. 需要渲染的回應欄位

僅回傳公開面資料——**不包含**寄件人/收件人完整地址（那些只在需登入的內部追蹤介面中出現）。

| field | meaning |
|---|---|
| `result` | `true` when a live order was found |
| `data` | Event timeline (newest first) |
| `data[].tracking_event_status_id` | Numeric code — match the dictionary on this page |
| `data[].otep_status` | Open tracking code when mapped (same bridge as the **otep** column) |
| `data[].description` | Localized customer text for this event |
| `data[].updated_at` / `timestamp` / `updated_at_localized` | When it happened (UTC string, unix, local clock) |
| `data[].location_*` / `operation_location` | Where it happened, when known |
| `data[].reason` | Public return/failure reason text when present |
| `deliveried` / `returntosender` / `rejectedbyrecipient` | Coarse final-state flags for header chips |
| `postcode` | Normalized delivery postcode (for POD gate on your side if you need it) |
| `proofs[]` | Signature / photo files (`url`, `full_url`, `signed_url`, `type`, `file_id`) |
| `is_third_party_tracking` / `third_party_info` | Present when a label/carrier timeline was merged in |

### 4. 建議介面流程

1. 從訪客處取得運單號，呼叫公開 GET 介面（可選帶 `Accept-Language`）。
2. 若 `result` 為 false 或 HTTP 為 404，顯示未找到並結束。
3. 用 `data[0]`（最新事件）做頁首狀態：人類可讀文案優先用 `description`；圖示/進度邏輯用 `tracking_event_status_id` 或 `otep_status`。
4. 將完整 `data` 列表渲染為時間線（已是新→舊）。僅在必要時分組或過濾——不要編造未發生的節點。
5. 若 `proofs` 非空且最新狀態為成功節點（通常 500 或 510），提供「查看簽收證明」；需要時效連結用 `signed_url`，需要本站永久路徑用 `full_url`。

### 5. 進度條 / 步驟條

**不要**為所有包裹寫死同一條鏈路。請對照本頁字典與流轉規律：多數末端配送為 100 → 300/301 → 450 → 500；雙段行程會先出現取件側 460 → 510。請按 `otep_status` 或 `tracking_event_status_id` 分支；出現異常或糾正時以最新事件為準。

### 6. 簽收證明

`proofs[]` 在可用時攜帶照片/簽名中繼資料。你的頁面仍可選擇用郵遞區號驗證後再展示；介面回傳正規化的 `postcode` 欄位供此用途。切勿在完全公開的頁面上展示完整收件街道地址。

### 7. 相關公開介面

依技術堆疊選擇合適入口。除非 API 文件另有說明，下列均為公開介面（無需 Token）。

| surface | when to use |
|---|---|
| `GET https://api.superlabel.ca/api/v1/tracking/{tracking_number}` | Default branded tracking page (this guide) |
| GraphQL `trackingPublic(trackingNumber: …)` at `https://api.superlabel.ca/graphql` | Same payload when your stack is GraphQL-first |
| `GET https://api.superlabel.ca/api/v1/otep/trackings/{tracking_number}` | Vendor-neutral OTEP timeline / EPCIS / ONE Record / UN-CEFACT projections |

### 8. 最小範例

```bash
curl -sS -H "Accept-Language: en" \
  "https://api.superlabel.ca/api/v1/tracking/SR1234567890"
```

```javascript
const res = await fetch(`https://api.superlabel.ca/api/v1/tracking/${encodeURIComponent(tn)}`, {
  headers: { "Accept-Language": "chs" },
});
const body = await res.json();
if (!body.result) {
  // show "not found"
} else {
  const events = body.data || [];          // newest first
  const latest = events[0];
  const proofs = body.proofs || [];
  // render latest.description, map latest.tracking_event_status_id or otep_status for the stepper
}
```

## 常見運單流轉規律

以下是**典型路徑**，不是強制狀態機。真實時間線會跳過步驟（例如無入庫掃描）、插入異常，或在同一訂單上交錯出現取件側與配送側事件。數字為 `tracking_event_status_id`；公開時間線僅展示 `tracking.visible = 1` 的列（見上方表格）。整合請按 `status_id` / `key` 分支，並以最新事件（id 最大）為準。

### 入倉 → 末端配送

最常見的自有運力路徑：下單 → 包裹入倉 → 司機開始派送 → 成功或配送異常。規劃類代碼如 400/401/402 可能在字典中存在，但通常**不對客戶可見**。

```mermaid
flowchart LR
  s100["100 information_submitted"] --> s300["300 received / 301 arrival_scan"]
  s300 --> s450["450 start_delivery"]
  s450 --> s500["500 deliver_success"]
  s450 --> s501["501 need_rescheduled"]
  s450 --> s502["502 redelivered_later"]
  s450 --> s503["503 not_delivered"]
  s450 --> s700["700 rejected_by_recipient"]
  s501 --> s450
  s502 --> s450
```

### 攬收 / 純取件段

司機外出取件，記錄取件成功（可帶簽收證明）或取件異常。純取件訂單停留在取件側；雙段行程在 510 之後進入配送側序列。

```mermaid
flowchart LR
  s100["100 information_submitted"] --> s460["460 start_pickup"]
  s460 --> s510["510 pickuped"]
  s460 --> s512["512 repickup_later"]
  s460 --> s513["513 not_pickuped"]
  s512 --> s460
```

### 雙段行程（先取後派）

適用於一次行程既有攬收又有送達——例如帶取件的配送、點對點、以及多數多段轉運。時間線通常先出現**取件側**節點（460 → 510），再出現**配送側**節點（450 → 500）。描述文案由事件側別選擇，不是由訂單類型選擇。

```mermaid
flowchart LR
  s100["100 information_submitted"] --> pickup["Pickup-side: 460 → 510"]
  pickup --> delivery["Delivery-side: 450 → 500"]
  pickup --> pFail["Pickup exception: 512 / 513"]
  delivery --> dFail["Delivery exception: 501 / 502 / 503 / 700"]
```

### 第三方 / 承運商履約

承運商下單可能產生 110/120；產品策略將其在公開時間線**隱藏**，使第三方與自營體驗一致。之後可見節點與倉配+末端一致（300/301 → 800 出庫 → 450 → 500）。承運商終態取消使用 403（不是 402；402 僅用於自營改派/路線取消）。

```mermaid
flowchart LR
  s100["100 information_submitted"] --> s110["110 / 120 hidden on public timeline"]
  s110 --> s300["300 / 301 warehouse"]
  s300 --> s800["800 package_outbound"]
  s800 --> s450["450 start_delivery"]
  s450 --> s500["500 deliver_success"]
  s450 --> sFail["501 / 503 / 600 / 700"]
```

### 即時配送（任務調度）

使用獨立字典（不在上方取件/配送側表中列出）。主路徑：已提交 → 分配騎手 → 前往取件 → 已取件 → 派送中 → 已送達。改派（411）與分配取消（412）可在開跑前循環；失敗後的改期使用 501。

```mermaid
flowchart LR
  s100["100 information_submitted"] --> s410["410 rider_assigned"]
  s410 --> s411["411 reassigned optional"]
  s410 --> s412["412 assignment_cancelled"]
  s412 --> s410
  s410 --> s460["460 start_pickup"]
  s460 --> s510["510 pickuped"]
  s510 --> s450["450 start_delivery"]
  s450 --> s500["500 deliver_success"]
  s450 --> s501["501 need_rescheduled"]
```

### 異常與終態代碼（速查）

| status_id | key | 常見含義 |\n|---|---|---|\n| 501 | need_rescheduled | 配送失敗，需重新計劃 |\n| 502 | redelivered_later | 同路線稍後重試 |\n| 503 | not_delivered | 配送異常 / 投遞失敗 |\n| 512 | repickup_later | 取件失敗，稍後重試 |\n| 513 | not_pickuped | 取件異常 |\n| 600 | return_to_sender | 退回寄件人 |\n| 700 | rejected_by_recipient | 收件人拒收 |\n| 403 | cancelled | 終態取消（區別於 402 路線取消） |\n| 402 | route_cancelled | 路線取消 / 改派（通常不對客戶可見） |

### 整合方經驗法則

1. 客戶最關心的主路徑錨點：**100** 已建立、**300/301** 已入倉、**450** 派送中、**500** 已送達；攬收段為 **460** 外出取件、**510** 已取件。
2. 不要假設固定完整鏈條——入庫掃描可選、第三方中轉（800）、雙段側別切換都很常見。
3. 異常（501–503、512–513、600、700）可出現在「外出…」之後；重新計劃後訂單可能再次進入 450/460。
4. 公開頁忽略不可見字典列；Webhook 與內部工具仍可能收到。糾正或撤銷先前成功時，始終以最新事件 id 為準。

諸如 `{warehouse_name}` 的佔位符會在執行時替換為真實倉庫或地點名稱。新字典列與可見性變更透過遷移發布；本頁每次請求重新讀取表，不會相對本環境過期。