> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.orderupb2b.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.orderupb2b.com/_mcp/server.

# 錯誤碼

## 兩種錯誤形狀

絕大多數的錯誤——驗證失敗、找不到資料、簽章或憑證問題——都是同一個形狀：

```json
{
  "error": "invalid_page_size"
}
```

`error` 是 snake\_case 字串，依代碼判斷失敗原因。極少數沒有被個別端點攔截、真正非預期的伺服器錯誤，會改用另一個形狀：

```json
{
  "code": "InternalServerError",
  "message": "internal error"
}
```

遇到這個形狀代表發生了未被歸類的例外，通常是 OrderUp 端的問題，不是請求本身有錯——請聯繫 OrderUp，並附上發生的時間，方便查證。

## 完整對照表

| 狀態碼   | `error`                                                                 | 原因                                                                |
| ----- | ----------------------------------------------------------------------- | ----------------------------------------------------------------- |
| `400` | `invalid_page`                                                          | `page` 小於 1，或換算出的位移量超出可表示範圍                                       |
| `400` | `invalid_page_size`                                                     | `pageSize` 不在 1–100 之間                                            |
| `400` | `invalid_updated_since`                                                 | `updatedSince` 不是合法的 ISO-8601，或沒有帶明確時區位移／`Z`                      |
| `400` | `invalid_parameter`                                                     | 查詢參數無法繫結成正確型別（例如 `page=abc`），或是各端點寫入邏輯裡沒有更具體對應代碼的失敗原因             |
| `400` | `empty_batch`                                                           | 批次端點收到空陣列或沒有 body                                                 |
| `400` | `internalUserId required: no default 負責業務 available`                    | 建立客戶未帶 `internalUserId`，且該租戶沒有設定預設負責業務（這句英文本身就是代碼，不是 snake\_case） |
| `400` | `product_category_id_required`                                          | 建立商品未帶 `productCategoryId`                                        |
| `400` | `invalid_product_category_id`                                           | 分類不存在、不可指派（根分類），或屬於其他租戶——三種情況統一回同一個代碼                             |
| `400` | `outerSysCode is required to create a SKU`                              | 建立規格未帶 `outerSysCode`（這句英文本身就是代碼，不是 snake\_case）                  |
| `400` | `productId is required to create a SKU`                                 | 建立規格未帶 `productId`，或帶入非正整數（同樣不是 snake\_case）                      |
| `400` | `bundle SKU cannot be updated through this API`                         | 更新的規格是組合品（Bundle）型別，這類規格無法透過本 API 更新（同樣不是 snake\_case）            |
| `400` | `{field}_too_long`                                                      | 有送出的欄位超過長度上限；完整對照見「欄位長度上限」                                        |
| `400` | `account_required`／`name_required`／`email_required`／`password_required` | 建立後台使用者缺少對應的必填欄位                                                  |
| `400` | `account_already_used`                                                  | 建立後台使用者，`account` 在同租戶內已被使用                                       |
| `400` | `invalid_role_id`                                                       | `roleId` 省略、不存在，或屬於其他租戶——三種情況統一回同一個代碼                             |
| `400` | `invalid_status`                                                        | 更新後台使用者，`status` 不是 `Active` 或 `Inactive`                         |
| `401` | `unauthorized`                                                          | 簽章、時間戳記或 nonce 其中一項驗證沒有通過                                         |
| `403` | `forbidden`                                                             | 簽章驗證通過，但你的憑證未開通此項操作                                               |
| `404` | `not_found`                                                             | id 不存在，或屬於其他租戶——兩種情況無法從回應內容區分                                     |
| `409` | `last_active_admin`                                                     | 這個後台使用者是租戶目前唯一還能登入的系統管理員，這次寫入會讓租戶失去所有可登入的系統管理員，因此被拒絕              |

## 401：驗證失敗

`401` 一律代表簽章、時間戳記或 nonce 其中一項驗證沒有通過，從呼叫端角度完全無法區分是哪一項——回應本身不會說明原因，避免洩漏線索給攻擊者。完整的逐項排查清單見「驗證與簽章」最後一節，這裡不重複。

## 403：憑證未開通此項操作

簽章驗證通過，但你的憑證未開通此項操作。請聯繫 OrderUp 開通。

## 404：id 不存在，或屬於其他租戶

`GET` 單筆端點與庫存查詢的 404 一律是 `{ "error": "not_found" }`。

判斷「找不到」請只看 HTTP 狀態碼，不要比對 `error` 字串本身。更新客戶／商品／規格（`PUT /v1/customers/{id}`、`PUT /v1/products/{id}`、`PUT /v1/skus/{id}`）如果 id 不存在或屬於其他租戶，回傳的 404 body 帶的是該資源專屬的簡短說明文字（例如「查無客戶資料」），不是固定的 `not_found` 代碼；後台使用者的更新端點則一律回傳 `not_found`。不論哪一種，狀態碼都是 404，依狀態碼判斷比依 `error` 字串判斷可靠。

## 409：狀態衝突（僅後台使用者）

`409 last_active_admin` 是這份文件目前唯一的 `409`，只會出現在 `PUT /v1/internal-users/{id}`。請求本身格式正確，衝突的是系統目前的狀態：這個使用者是租戶目前唯一還能登入的系統管理員，若這次寫入把他改成非管理員角色、或把狀態設為 `Inactive`，租戶會失去所有可登入的系統管理員——這支端點會拒絕該次寫入，而不是靜默放行。

## 下一步

#### [驗證與簽章](/authentication)

401 的完整排查清單：時鐘飄移、nonce 重複使用、query string 正規化等常見原因

#### [欄位長度上限](/field-limits)

`{field}_too_long` 對應的完整欄位與長度上限對照表