API 文档
帮助中心 / API 文档

API 文档

把 Docklify 和你现有的系统集成起来。

以编程方式访问 Docklify。所有接口都限定在你的组织范围内。

  • Base URL: https://app.docklify.com
  • 鉴权 — Authorization 头带 Bearer <redacted>,同时传 x-organization-id 指定租户。
  • 分页 — 列表接口接受 page(默认 1)与 page_size(默认 50,最大 200);响应带 meta { total, page, page_size }。

WMS · 仓储管理

入库收货32 个接口

入库单/api/wms/inbound-receiptsGETPOSTPATCH19 个接口

GET/api/wms/inbound-receipts

入库单列表查询:按单号/状态/日期/承运商等条件筛选入库单,支持一体搜索和排序,用于入库单列表页。

POST/api/wms/inbound-receipts

创建入库单:入库的"开单"动作,登记这票货从哪来(采购/手动/门户/甩柜/退货)、预计哪天到、有哪些商品。创建后状态为 new。

GET/api/wms/inbound-receipts/{id}

入库单详情:看一张入库单的完整信息、每条明细的预期/已收/剩余数量、收货进度,以及关联的收货任务状态。

PATCH/api/wms/inbound-receipts/{id}

编辑入库单头:仅可编辑状态(draft/new/receiving)可改(承运商/箱柜号/预计到货日/实付费用/货主等)。2026-10-24(REQ-20261024-35):可传 `rma_id` 关联/换绑 RMS RMA(S9),传 null 解除关联;校验与 POST 建单同一 helper(`saas/app/api/wms/lib/rma-link.ts`)。

POST/api/wms/inbound-receipts/{id}/clear-direct-events

清除入库单上非托盘的直接收货记录,并回滚库存和收货行数量。

POST/api/wms/inbound-receipts/{id}/clear-receiving

清除收货进行中的草稿数据(building 托盘、未完成收货任务),已提交的收货数量不动。

POST/api/wms/inbound-receipts/{id}/close

关闭入库单:received → closed(关闭后所有字段锁定)。

POST/api/wms/inbound-receipts/{id}/complete-receive

桌面直操"完成收货":全部行收完 → receipt→received,触发 Purchase/Drayage 回写;自动补建 completed receive task(含工时记录),锂电池 true 时 needs_inspection 弹窗。

GET/api/wms/inbound-receipts/{id}/events

入库单收货历史时间线:每次确认收货一条,带操作人、库位和商品。

POST/api/wms/inbound-receipts/{id}/landed-cost/recalc

按实付费用重算整票到岸成本:分摊到每行写 unit_landed_cost,并回写整票结果。

POST/api/wms/inbound-receipts/{id}/receive-all

桌面一键收货:逐行确认收货数量,全部收完自动把入库单置为 received。

POST/api/wms/inbound-receipts/{id}/receive-batch

批量收货:一次确认 N 行(每行独立校验+批次/效期/序列号追踪,任一行失败整体 400);任务制时可选 task_id 写步骤日志;全部收完→received。

POST/api/wms/inbound-receipts/{id}/receive-line

单行收货确认:批次/效期/序列号强制校验,写 receiving_events + lot/serial 库存台账;计重产品可传 received_weight。

POST/api/wms/inbound-receipts/{id}/receive-pallets

按托一键入库:逐托盘校验后整托写库存,全部处理完入库单置为 received。

POST/api/wms/inbound-receipts/{id}/rollback

把收货中的入库单回滚到 new(已有收货数量时拒绝,一并清除收货草稿)。

POST/api/wms/inbound-receipts/{id}/start-receiving

手机点"开始收货"时立即把入库单置为 receiving(幂等)。

POST/api/wms/inbound-receipts/{id}/un-receive

反收货:received → receiving,清空所有明细行的已收数量和收货人时间。

POST/api/wms/inbound-receipts/batch-close

批量关闭入库单:只有 received 的会被关闭,其他状态跳过并说明原因。

POST/api/wms/inbound-receipts/import

批量导入入库单:收浏览器解析好的 JSON 行,按 receipt_id 分组建单,逐行校验不整体回滚。

ASN 到货通知/api/wms/asnGETPOST2 个接口

GET/api/wms/asn

ASN(预到货通知)列表,支持按状态和单号模糊搜索

POST/api/wms/asn

接收客户 EDI/API 推送的 ASN(含 HU 明细),同组织同单号幂等(已存在直接返回已有)

预约/api/wms/appointmentsGETPOSTPATCH11 个接口

GET/api/wms/appointments

预约列表(支持按预约单号/承运商/客户/状态/日期范围筛选,附下拉选项)或日历模式(按周聚合每天每小时各服务类型的预约数)

POST/api/wms/appointments

创建一条仓库预约(生成 APPT- 单号,写入预约主表+服务明细+入库单关联)

GET/api/wms/appointments/{id}

预约单详情:预约主表 + 服务明细 + 关联入库单(含货主名称)。

PATCH/api/wms/appointments/{id}

编辑预约单:改承运商、预约日期时间、备注或状态。

PATCH/api/wms/appointments/{id}

编辑预约单:改承运商、预约日期时间、备注或状态。

PATCH/api/wms/appointments/{id}/cancel

取消预约(当前为 mock:不写库,直接返回 CANCELLED 状态)。

POST/api/wms/appointments/{id}/actions

预约确认回路动作(REQ-20261025-19 P1):action=confirm(满额须 overbook=true + overbook_reason 留痕,服务端强制校验、无原因回 400 APPT_OVERBOOK_REASON_REQUIRED)/ propose(给替代时段 window_start/end + note)/ reject(reason 必填)/ cancel(双向,通知对方);状态流转经条件更新防并发,冲突回 409 大白话。P2 增:cancel 成功后连带 active 指派行置 cancelled+guest 令牌吊销;action=assign(指派/改派司机:driver_id 选名录司机或现填姓名+手机号,walkin=true 为仓库代录;回 {assignment, driver_guest_link, carrierSnapshotPending})/ action=save-carrier(把名称快照一键存入 shared_carriers 名录并回填 carrier_id)

GET/api/wms/appointments/{id}/actions

指派弹窗数据(REQ-20261025-19 P2):当前 active assignment+本预约 carrier 名下司机名录(白名单字段)+预约 carrier/状态摘要

GET/api/wms/appointments/slots

时段余量(仓库+日期+方向):按组织档位切分,逐档回 capacity/used/remaining(capacity=null 不限);计数口径与申请占额、仓库确认校验同一 lib(lib/appointment-capacity.ts)

GET/api/wms/appointments/verifications/{id}

GET /api/wms/appointments/verifications/{id} — 司机核验会话审核卡(Docklify 面,D127):证据只在会话内可见,每次文档查看先写访问日志、写失败即不出数据(fail-closed);审核员门=yms.appointments view 点

POST/api/wms/appointments/verifications/{id}/review

POST /api/wms/appointments/verifications/{id}/review — 司机核验审核动作 {action: approve

越库38 个接口

越库/api/wms/cross-dockGETPOSTPATCHDELETE38 个接口

GET/api/wms/cross-dock/appointment-board

Cross Dock 进出衔接看板(二期⑥):把当天进行中的 receiving/shipping 任务与当天进出预约按目的地配对,一眼看出「货到没车 / 车到没货」(一侧任务或预约缺失即为空)。配对口径:inbound 侧取该目的地第一个 receiving 任务,预约按 `reference_no` = 任务入库单的 `receipt_no` 匹配;outbound 侧取该目的地第一个 shipping 任务,预约按 `load_id` 匹配。任务范围 = 本组织 `wms_cross_dock_tasks` 中 status ∈ open/in_progress(上限 200 条);预约范围 = `wms_appointments` 中 appt_date = 指定日期且 status 不在 CANCELLED/NO_SHOW(按 appt_time 升序,上限 200 条)。注意:pairs 只由任务驱动生成——当天有预约但无进行中任务的目的地不出现在结果里。目的地显示名 = `wms_destinations` 的「destination_code + 空格 + name」,查不到时回落显示 destination_id 本身;任务无 destination_id 时归入「未指定」组。本端点无业务参数错误(仅登录/组织鉴权失败走统一错误信封)。

GET/api/wms/cross-dock/change-destination

查某个 HU 的目的地变更历史(审计记录,时间倒序)。另支持整单聚合模式:传 receipt_id(与 hu_id 二选一,receipt_id 优先)时返回该收货单名下全部 HU(含拆包子 HU)的变更历史,先验收货单属本组织,changed_at 倒序、服务端分页(page_size 上限 100),每行带 sscc 与 changed_by_name(服务端按组织成员 display_name 批量解析,查不到为 null);响应带 meta{total,page,page_size}。

POST/api/wms/cross-dock/change-destination

批量改 HU 目的地(只允许未出库状态 expected/received/staged,已出库 HU 报 400),每单写审计记录。

GET/api/wms/cross-dock/destinations

目的地主数据列表;可按编码/名称/城市模糊搜、按货主/启用状态筛选。

POST/api/wms/cross-dock/destinations

新建目的地;同组织内 destination_code 唯一,国家默认 US。

DELETE/api/wms/cross-dock/destinations/{id}

删除目的地;有 HU 引用时拒绝(报 400,可停用代替)。

PATCH/api/wms/cross-dock/destinations/{id}

更新目的地(含停用);空字符串传值会置为 null。

GET/api/wms/cross-dock/exceptions

异常单列表;可按索赔状态(多值逗号分隔)、异常类型、任务筛选,支持 SSCC/描述/异常单号(exception_no,EXC-…)模糊搜;每行带 exception_no、photo_count 和任务号。

POST/api/wms/cross-dock/exceptions

登记异常单(初始 claim_status=draft,同步 HU 的 claim_status 冗余字段);落库时经全站统一单据序列(shared_doc_sequences,doc_type=wms_cross_dock_exception)发人读编号 exception_no(EXC-000001 起);同一 HU 已有未关闭异常单时报 409(details 带现有单 exception_no)。

GET/api/wms/cross-dock/exceptions/{id}

异常单详情:异常单整行 + 任务号 + 照片(文档 ID 换成新鲜签名链接)。

PATCH/api/wms/cross-dock/exceptions/{id}

索赔流转:draft→submitted→approved/rejected→paid,任意步可→closed(closed/paid 写 resolved_at、记经办人、同步 HU 冗余状态)。

POST/api/wms/cross-dock/exceptions/{id}/photos

上传破损照片(multipart/form-data,字段名 file;单张≤10MB;单张异常单最多 5 张;已关闭异常单不可再传)。文件走统一文档中心,photos 存文档 ID。

GET/api/wms/cross-dock/handling-units

HU 查询:支持 SSCC/暂存区模糊、状态/状况/货主/入库单/装车单/目的地筛选;每行附目的地显示、明细行、入库单号、出库车号。

GET/api/wms/cross-dock/monitor

Cross Dock 监控看板数据:收/出/在场/破损汇总、按天收发趋势、滞留超阈 HU(带 dwell_hours)、按目的地分组在场数与近 N 天平均滞留时长、当前滞留预警阈值。

GET/api/wms/cross-dock/inventory

越库库存查询(D112):在场过站货的存量聚合——summary 七项 / 按产品(SKU)聚合 / 按目的地聚合。与 monitor 分工:monitor 是流量/异常视角,本端点是存量查询视角;在场集、超期阈值、今日进出定义与 monitor 同源同口径(见设计稿 D112 §3)。

GET/api/wms/cross-dock/open-loads

当班可预选的越库装车单(2026-10-24 新增,REQ-20261023-09 P2-1):返回同仓、当天(UTC 日界,与月台看板同口径)、未关闭(状态不在 fulfilled/delivered/cancelled,单一事实源 `XD_LOAD_CLOSED_STATUSES`,取值与 wms_load_status 枚举对齐)的 cross_dock loads。收货页「直转」自动预选判定走此端点(恰一张才预选),不再客户端按状态白名单自算——此前客户端口径无当天限定、与服务端关闭定义不一致且受分页窗口漏计。

POST/api/wms/cross-dock/opportunity-match

Cross Dock 机会型匹配推荐(只读,永不自动绑定;确认绑定走 POST /api/wms/cross-dock/change-destination 审计链)。匹配逻辑单一实现 `cross-dock/lib/matching.ts`,与 scan 的 receive 分拨推荐共用。在站 HU 侧(传 hu_id 或 sscc):HU 已有目的地时短路——`already_assigned=true`、recommendations 为空;HU 明细无 SKU 时 recommendations 为空并带 `note="no_sku"`;否则按 HU 明细 SKU 匹配 HU 所属仓库(经入库单取 warehouse_id,不跨仓)的 open 出库单(status ∈ draft/picking/packing/staged、行未发运完)需求,按出库单 ship_to city+state 对到启用的 wms_destinations 后按目的地聚合(matched_qty 降序;目的地主数据未匹配上的需求归入 destination_id=null、destination=「未匹配目的地主数据」一组;每组 orders 最多 5 条)。三期 S8:响应另附 stored_matches(在库整托直出候选)——仓库范围取 body 的 warehouse_id,未传时回落 HU 入库单的仓库,两者皆无则 stored_matches 为空;只传 warehouse_id(不传 HU)时只算 stored_matches(桌面直出面板用法),此时 sscc=null、already_assigned=false。整托口径:available、qty>0、未被订单占用、有 LP 标识且有库位的库存行按托分组,仅单 SKU+单货主托入选,FIFO(received_at 升序)整托贪心累计恰好等于需求 remaining(ordered − shipped − 已确认直出量)才命中,拆零不出现;client_id 传了则只算该货主的 open 出库单需求。stored_matches 计算失败被吞为空数组,不挡在站 HU 推荐。错误:hu_id、sscc、warehouse_id 三者皆不传 → 400 `WMS_VALID_001`(details.field="hu_id",message「hu_id、sscc 或 warehouse_id 必填其一」);warehouse_id / client_id 非合法 UUID → 400 `WMS_VALID_001`;HU 在本组织不存在 → 404 `WMS_NOT_FOUND_001`(message「HU 不存在」)。

POST/api/wms/cross-dock/opportunity-confirm

S8 整托直出确认(三期,2026-10-24,REQ-20261023-11):{shipment_id*, lp_no*(sscc 别名), location_id?};服务端复算整托(单 SKU/单货主/未占用/不超需求 remaining),库存托盘登记为 HU(source_type='inventory'、id_type='internal'、LPN 作标识、status='staged'、source_shipment_id=需求单),占用走既有 commit 锁 lockInventoryForCommit(reference=需求单)+ detail 行 order_id 标记;预登记不写库存发生额。实现 `cross-dock/lib/direct-out.ts

POST/api/wms/cross-dock/opportunity-release

S8 直出释放(三期,2026-10-24,REQ-20261023-11):{hu_id*};仅 source_type='inventory' 且未装车(status='staged'、无 load_id)的 HU——unlockInventoryForRelease 释放锁、清 detail 占用标记、删 HU+行(预登记非实物事件,审计留痕),库存零发生额;已装车 400(走 close 扣账口径)

POST/api/wms/cross-dock/handling-units/{id}/service-hold

VAS 转增值加工/挂起(三期,2026-10-24,REQ-20261023-11):{template*(labeling 贴标/relabeling 换标/assembly 组装), work_order_id?};HU 须 received/staged 且未挂起。组装未传工单时经既有 createWorkOrder 建 Assembly 工单并链接;贴标/换标只落挂起+模板留痕(工单系统暂无服务工单载体)。置 service_hold/service_hold_at/service_template/service_work_order_id(migration 545),审计留痕;挂起期间 scan load 硬拦 409

POST/api/wms/cross-dock/handling-units/{id}/service-release

VAS 加工放行(人工)(三期,2026-10-24,REQ-20261023-11):累计本次挂起秒数落 service_hold_seconds(滞留扣减口径,lib/dwell 统一消费),清挂起标记/工单链接,HU 状态/目的地/格口不变。组装工单的 HU 一般由工单 complete/cancel 钩子自动放行(`releaseServiceHoldByWorkOrder`),本端点为贴标/换标唯一放行口与人工兜底

POST/api/wms/cross-dock/break-bulk

拆箱分拨(二期 S4,2026-10-24,REQ-20261023-10,设计 §5.2/§5.3):把一台母 HU 的部分(或全部)明细拆成子 HU,可分别指定目的地。母 HU 必须 received/staged;loading/shipped/exception/split/stored 拒 400(说人话六语)。子 HU 继承 client/receipt/格口/柜号/状况/到仓时刻(dwell 连续),不继承 stage 预绑;子码为内部码(`XD-SPLIT-…`,id_type=internal,用贴标机打子标签)。母行数量断言:拆出量 ≤ 母行余量,拆空删行,母全部拆空 → 母 status=split。留痕:wms_audit_log(action=wms.cross_dock.break_bulk,对账明细);带 task_id 时写 scans 一行 scan_type=split。再扫已拆母码走 scan 端点的 split 兜底(回子清单)。

POST/api/wms/cross-dock/convert-to-putaway

待分拨池转上架(二期 S5,2026-10-24,REQ-20261023-10,设计 §6.3):无去向的在场 HU 转成标准上架任务留仓。守卫:HU 须 received/staged、无 stage 预绑(bound_load_id)、无未完成同源上架任务、有入库单与仓库;有目的地时须 supervisor_id+reason 改判(主管放行单一口径,自批拒)。动作:建 wms_tasks(task_type=putaway, source_doc_type=cross_dock_hu)+wms_putaway_task_lines(SKU 查 wms_items,查不到 400 列明不静默丢量;genDocNo TSK+SLA+自动指派与 receive-complete 同口径);HU→status=stored、清 destination_id;审计 wms.cross_dock.convert_to_putaway。**2026-11-04 REQ-20261104-47 修订(Andy 定版,取代「零库存写入」旧口径)**:转换瞬间把 HU 物化为标准托盘并落账——wms_pallets 新行(lpn=pallet_no=HU 的 SSCC、label_source='factory'、status='staged'、location_id=HU 暂存格口、receipt_id=HU 入库单、pallet_lines=HU 内容行;按 SSCC 解析既有托盘幂等复用)+逐内容行 wms_inventory_lot upsert(位置=暂存格口、inventory_status='available')+ledger 'receive'(status='available')+wms_inventory_detail 镜像(落账口径与普通收货一致;越库 scan 从不写库存,两路径互斥不双重落账;该托 lot 已在位则跳过落账段);wms_putaway_task_lines 回填 pallet_id;HU 无暂存格口先行 400 拦截;任一步失败全量补偿(任务删行删头、ledger 以 'adjust' 反向腿对冲、删自建 lot/detail/托盘)。上架任务自此为「LPN 移位」:执行端预带锁定该 LPN、只扫目标库位确认,完成时库存位置由暂存格口更新为目标库位。

POST/api/wms/cross-dock/bind-to-load

S7 stage 预绑(二期,2026-10-24,REQ-20261023-10,设计 §8.2):分拨时把 HU 预绑到某台 load,装车时优先装预绑车;齐套判定与关闭门都读 bound_load_id(HU.load_id 保持「已装车」语义不变)。绑定守卫:HU 在场(received/staged)、未装车、未绑他车、有目的地;load 未完结且其目的地集(load_destinations ∪ destination_id)包含 HU 目的地。解绑(load_id=null)守卫:已装车不可解绑。留痕 wms_audit_log(bind_to_load/unbind_from_load)。

GET/api/wms/cross-dock/loads/{id}/merge-status

S7 齐套只读(二期,2026-10-24):返回 load 的 merge_policy 与齐套判定(与 close 关闭门同一实现 `cross-dock/lib/merge.ts`)。判定仅当 load 有 ≥1 预绑 HU 时 active;应到集=预绑 HU ∪ 未预绑且目的地∈load 目的地集的 expected HU;实到=预绑且 staged/loading;缺口=应到−实到−已发运。

POST/api/wms/cross-dock/loads/{id}/merge-policy

变更合流策略的唯一受控入口(2026-11-06 新增,Merge 三件批件 2):body `{ merge_policy*(wait_complete/partial_allowed), supervisor_id*, supervisor_password*, supervisor_override_reason* }`;服务端硬校验——三要素缺一 400 `MERGE_POLICY_NEEDS_SUPERVISOR`、禁自批、主管资格(supervisor-approval 单一事实源)、密码再认证(错回 `SUPERVISOR_PASSWORD_INVALID`)、已关闭 load 拒改;同值幂等回 `changed=false` 不写审计;变更落审计 `wms.cross_dock.merge_policy_change`(old→new+操作人+审批主管+原因,审计写失败回滚改值)。通用 PATCH /api/wms/loads/{id} 已摘除 merge_policy(见下)

POST/api/wms/cross-dock/loads

建 load(补登 merge_policy,2026-10-24 二期):body 可选 `merge_policy`(wait_complete 默认 / partial_allowed,仅 cross_dock 有意义,其他类型忽略)

PATCH/api/wms/cross-dock/loads/{id}

更新 load(补登 merge_policy,2026-10-24 二期):UPDATABLE 含 `merge_policy`(枚举校验,非法 400;空串跳过)。**2026-11-06 起作废此口径**:实际路由为 PATCH /api/wms/loads/{id},merge_policy 已摘除——显式带该字段回 400 `WMS_VALID_001` 并指路 POST /api/wms/cross-dock/loads/{id}/merge-policy(主管口径受控端点);建单时 POST /api/wms/loads 显式选策略不变

POST/api/wms/cross-dock/loads/{id}/close

关闭 load 发车。2026-10-24(二期 S7 齐套门,REQ-20261023-10):load 有预绑 HU 且 merge_policy=wait_complete 未齐套 → check_only 回 merge 缺口、正式关闭 fail 列缺口 SSCC;partial_allowed 放行须 supervisor_override+supervisor_id+supervisor_reason(自批拒、放行审计 fail-closed),缺口预绑 HU 自动改绑下一班同目的地 load(找不到则解绑并在响应明示);关闭后仍绑本车未发运 HU 一并结算,响应加 merge/merge_rebinds

POST/api/wms/cross-dock/reprint-label

HU 标签重打:按 SSCC 返回标签数据(SSCC、类型、目的地、产品明细),前端送打印机。

POST/api/wms/cross-dock/scan

Cross Dock 手机扫描核心:receive(收货建档/收破损进异常区)/ stage(分拨确认)/ load(装车;有未关闭异常单的 HU 报 409,目的地不匹配报 400);同一任务同一 SSCC 同一类型重复扫描返回 duplicate。SSCC 校验位(2026-10-24,REQ-20261023-16):sscc 恰为 18 位纯数字时按 GS1 Mod-10 验校验位(与 buildSscc 生成同源),不过回 400 `SSCC_CHECK_DIGIT_INVALID`(六语大白话,`?lang=` 定位);其他形态(柜号/封条/内部码)不验校验位、维持仅非空,不误杀。预绑口径(2026-10-24,REQ-20261023-09 NOTE-1/2):receive 时任务挂的 load 若在 `wms_load_destinations` 恰有一条明细则预绑该目的地;明细为空时回退读 load 的 `destination_id` 列(经典单目的地同样触发预绑);本次新建的 HU 无论经手选(picked)还是预绑(prebind)落定目的地,都补写一条 dest history(reason 分别为 on_receipt_select / transload_prebind),与既有 HU 补绑同一审计链(设计 §12.2)。二期(2026-10-24,REQ-20261023-10):receive 成功且 HU 仍无目的地时响应附 `needs_destination`+`recommendations`(匹配 lib 与 opportunity-match 共用,失败不挡收货);扫 status=split 的母 HU 码回 `{ split: true, children }` 子清单兜底;响应 data.hu 含 parent_hu_id/bound_load_id。终态 stored 兜底(2026-10-24,二期 review P2-2,设计 §12.1):扫 status=stored 的 HU 码(任一 scan_type)回 `{ stored: true, sscc, hu_id, putaway_task_no, putaway_task: { id, task_no, status } | null }`——上架任务号取 wms_tasks 中 source_doc_type='cross_dock_hu' 且 source_doc_id=该 HU 的最近一张,查不到时 putaway_task_no/putaway_task 为 null;meta.message 为六语大白话信息文案(`?lang=` 定位)。该分支与 split 兜底同位、在重复扫描保护之前判定,只读返回:不写 scans 记录、不改 HU 状态(stored 不再被 receive 翻回 received)。S9 处置映射自动绑(2026-10-24,REQ-20261024-35 包3):load 分支对 `source_type='return'` 的 HU 在处置已定校验通过后,若 HU 尚无目的地且其关联 RMA 已收货行 disposition 一致映射到同一 kind(rtv/dispose),经 `findDestinationByKind` 解析并自动绑目的地、写 dest history(reason=`disposition_mapping`,设计 §12.2 来源③);其余处置(restock/refurbish/donate)与混合处置不自动绑。收货回写入库单(2026-11-04,REQ-20261104-14):receive 时 HU 首次由 expected 跃迁为已收(received/exception),按 HU 内容行回写关联入库单行量(good→received_qty、damaged→damaged_qty,行完成口径 received+damaged+rejected≥expected 与普通收货链一致;逐行乐观并发累加)并推进入库单状态(首次收货→receiving、全行收满→received,完成复用普通链 completeReceipt);跃迁是唯一计数点,重扫(duplicate)与后续 stage/load/拆箱/转上架均不重复计数。响应 data 加 `receipt_writeback: { ok, receipt_status } | null`(非 receive 或未跃迁时为 null;回写失败不回滚收货、ok=false)。独立 review 窄修(同日):计数门为「跃迁 ∧ counted_receipt_id 未标记」双条件(标记 migration 850,跃迁同次 update 以状态 CAS 认领、任务取消不清除)——已计入本单的 HU 被取消打回后重扫只对账状态不重计、已计入他单报警不计数;HU 状态 update 带状态 CAS(eq 跃迁前状态),两台设备同扫一 HU 后到者 0 行按 duplicate 返回;部分失败(行累加重试耗尽/未匹配 SKU)时 ok=false 并带 `failed_line_ids`/`unmatched` 明细。

GET/api/wms/cross-dock/staging-slots

暂存格口选择器数据(设计 §12.3/§12.5):格口 = 本仓 `wms_locations` 中 location_type='staging' 的启用库位(单一事实源),服务端聚合当前占用数(HU 状态 received/staged/exception 且 staging_location_id 指向该格口)。2026-10-24(REQ-20261023-09 P2-2):占用聚合查询失败时 occupancy 返回 null(UI 显示「—」)且 meta 带 occupancy_degraded=true,选择器明示占用数暂时取不到——不再静默报 0 把满格显示成空格口。

GET/api/wms/cross-dock/tasks

Cross Dock 任务列表;可按任务类型/状态筛选。

POST/api/wms/cross-dock/tasks

新建 Cross Dock 任务:receiving(需 Cross Dock 类型入库单;或 Return Receipt 且已关联 RMA——S9 放行档,2026-10-24 REQ-20261024-35)或 shipping(需 cross_dock 类型 load + 目的地);幂等——同一单已有 open/in_progress 任务时直接返回现有任务。

GET/api/wms/cross-dock/tasks/{id}

Cross Dock 任务详情:任务头 + 扫描记录 + HU 明细 + 目的地(及本车目的地列表)+ 异常单数 + 预估费用(shipping 关闭前)+ 关联进出预约。

PATCH/api/wms/cross-dock/tasks/{id}

指派/改派(2026-10-21 新增,A2;既有 [id] 路由加方法、不新增路由):body `{ assignee_id }`(传 null 取消指派),口径镜像工单 PATCH——须为本组织成员(`WMS_VALID_001`),completed/cancelled 不可改派(`WMS_STATE_001`)。桌面端任务详情页指派选择走此端点

POST/api/wms/cross-dock/tasks/{id}/cancel

取消 Cross Dock 任务:仅 open/in_progress 可取消,本任务扫过的 HU 回滚状态(receiving→expected 并清空 receipt;shipping→staged 并清空 load)。

POST/api/wms/cross-dock/tasks/{id}/close

关闭 Cross Dock 任务:receiving 直接完成;shipping 按装车扫描的 HU 建出库单(多目的地按送货顺序一目的地一单)→ 挂到 load → 逐 HU 登记托盘与 SSCC 标签(沿用 HU 自身号,lib/wms-ucc registerExistingSsccPalletLabel)→ HU→shipped → 逐组全 shipped 后推进出库单 fulfilled(+shipped_at/shipped_by)与关联行 loaded → 记计费事件。2026-11-04(REQ-20261104-39)三缺修复:此前自动建的出库单无托盘/标签行(两页标签台账 SSCC 0/0)、状态停 draft、关联行停 planned,本批补齐;失败路径在 HU 状态落库前/推进中 fail 中止,不留半推进态。`?check_only=1` 为预检模式(只返回未收完的入库单警告,不关闭)。2026-10-21(统一 Close 设计 §6.3 #8):可选 body `reason_code/reason_note`——receiving 未收满(系统无 HU 级预告清单,未收满由工人在手机弹窗声明「还有 HU 没到」)时必传,服务端写入任务行 `close_reason_code/close_reason_note`(migration 498),且带原因的 receiving 关闭发统一通知 `wms.task.force_closed` 给原指派人、响应带 `force_close: true`;未到 HU 仍挂原入库单继续有效。shipping 关闭不要求原因,未装 HU 留在暂存区(staged)等下一车,不进本次出库单。收货回写对账(2026-11-04,REQ-20261104-14):receiving 关闭后按入库单行现状对账推进状态(cross-dock/lib/receipt-writeback 的 reconcileReceiptStatus:全行收满才 received、部分收货保持 receiving、received/closed 不回退;行量不在 close 重算),响应 data 加 `receipt_status`(任务无关联入库单或对账失败时不带;对账失败不挡关闭)。

出库与波次111 个接口

出库单/api/wms/shipmentsGETPOSTPATCH42 个接口

GET/api/wms/shipments

出库单列表查询,支持按单号/多字段模糊、状态、仓库、客户、发运方式、来源订单、承运商、日期、Order Attributes(is_single_unit/is_international/needs_repack/has_hazmat/is_oversize/is_gift 布尔过滤 + zone 数组包含)等多条件筛选;默认按创建时间倒序分页。每条结果带 OMS 订单号、零售商名、仓库名、客户名、Load 号等关联信息。

PATCH/api/wms/shipments

出库单批量操作:close(未发运单→cancelled)、rollback(状态回退一步)、update(批量改承运商/优先级/排期等字段)

POST/api/wms/shipments

创建出库单(单号 OO- 开头,由系统原子取号)。order_type 决定发运路径(不传默认 parcel):parcel 走 Packing Station 直发;freight 发运前必须先加入 Load;will_call 走自提流程。创建时同时写入明细行(wms_order_lines),虚拟 kit 会自动爆 BOM、实物 kit 会建 MTO 工单。明细行 + kit 处理成功后重算 Order Attributes 11 派生列(migration 462:is_single_unit/is_international/needs_repack/pick_zone_codes/has_hazmat/needs_temp_control/needs_serial_capture/needs_batch_tracking/line_count/total_units/is_oversize),重算失败则整个请求失败。单号 OO-;发运单(SP-)是另一实体,由系统在发运时自动产生,本接口不创建。

GET/api/wms/shipments/{id}

出库单详情:出库单全行 + 明细行(含产品 SKU/名称/描述/重量和各阶段数量)+ 零售商信息 + 来源 OMS 订单 + 关联 Load 号/MBOL 号 + 操作人姓名,并附总行数/总订购量/总已发量/进度百分比。

GET/api/wms/shipments/{id}/bol

取出库单级 BOL:已在 Load 中则返回其 Load 的 BOL,未入 Load 按出库单单独生成;仅限整车(parcel 单直接 409)。

PATCH/api/wms/shipments/{id}

更新出库单业务字段(详情页 Edit;白名单字段:急单/订单类型/承运商/服务等级/各类地址/备注等;store_id 传入时校验为本组织门店)。礼品三字段(is_gift/gift_wrap_type/gift_message)可直接维护。Order Attributes 重算触发(migration 462):明细行被整单替换(仅 draft)/ ship_to_country 变更 / warehouse_id 变更(须为本组织仓库)时重算 11 派生列;其他字段变更不重算。

POST/api/wms/shipments/{id}/pickup-ready

出货三方式(REQ-20261025-03 / D20 §5.3):客户自提「备好待取」(shipments 动作自注册,路由净增 0)。状态须 picked/packed/staged;写 `pickup_ready_at`(只记第一次)+联系人/备注(传了才覆盖;联系电话显式传 null 可清空),**不扣库存**。错误:`WRONG_ORDER_TYPE`(非 will_call)。已 fulfilled 回 already 幂等结果。**二期交接证据(REQ-20261031-28,设计 §12)**:ready 成功后落证据行(档位快照);标准/严格档抢占生成 6 位提货码并短信通知联系人(响应加 `pickup_tier`、`code_sent_via`);码生成失败整单报错、ready 可安全重试不留无码单。

POST/api/wms/shipments/{id}/pickup-complete

出货三方式(REQ-20261025-03):客户自提「已取走」——扣库存时点。body `{picked_up_by_name*(缺省取 pickup_contact_name), pickup_note?}`;须已 ready 且单据 packed/staged(ship core 状态门,picked 直接办透传 `WMS_STATE_001`,先 pack-confirm);扣账复用 shipShipmentCore(空承运商/空运单号、deduct 走既有分配汇总),置 fulfilled+`picked_up_at`/`picked_up_by_name`。错误:`PICKUP_NOT_READY`。重复 complete 回既有结果不双扣。2026-10-31 修复(REQ-20261031-31,契约不变):分配汇总的 owner 对账——allocate 台账腿记的是订单行指定 title(未指定=''),余额行是真实货权名,两者对不上曾使命名 owner 库存的自提单恒回 WMS_STATE_001;现归属分两遍(未指定腿按余额行真实 owner 归属)+commit 写腿落实际消费行 owner,场景 RG-0589/RG-0590。**二期(REQ-20261031-28)**:body 加 `pickup_code?`/`id_check?{type,last4}`/`signature_png*`/`id_photo_jpg?`(口径与 OMS complete 逐字一致,两路同一共享状态机)。拦截链:类型→幂等 already(含证据收尾对账)→Hold 预检→状态门(cancelled/fulfilled 先拦,不耗码 attempts)→`PICKUP_NOT_READY`→intake(经 order_id 读 OMS 订单 issues,联系人类 issue 按出库单联系人逐个消解、其余拦 `ORDER_INTAKE_INCOMPLETE` 指路 OMS)→提货码→证件(严格)→签名→姓名→扣账;证据五步时序同 OMS。详情 GET 同批加 `pickup_handover` 字段(证据视图;pending 的 code 仅对通过数据范围校验的员工下发)。

GET/api/wms/shipments/handover

承运商交接候选列表(manual 交接模式,migration 471):按承运商分组列本仓 status='packed' 出库单(含包裹 tracking 号、packed_at,上限 500 按 packed_at 升序)。query `warehouse_id*`。REQ-20261102-30 起每单增 `handable`/`block_code`/`shortage`(只加字段):handable=false+block_code='IN_PROGRESS'=正被另一交接请求认领处理(migration 779 的 handover_claimed_at 2 分钟内);shortage=true=有未拣量(与 buildShipmentDeduct 同口径聚合),提交后需走缺货确认。**2026-11-03 口径订正(REQ-20261103-14)**:已拣量归属与 zone-pick 进度同源——cluster/zone 拣选单按 `tote_splits` 逐单归属+拆行链收敛(lib/wms-ship-deduct 的 loadPickedShares,GET 缺货标识与 POST 扣减共用),不再只按 pick 行直挂 shipment_id 统计(旧口径把整批拣齐的 cluster 单误判缺货、交不出去)。权限 wms.outbound.edit+assertDataScope。

POST/api/wms/shipments/handover

承运商交接确认:body `{shipment_ids*(≤200), carrier?, confirm_shortage?, shortage_reason?}` → 逐单 shipShipmentCore(扣减+台账+OMS 回写)翻 fulfilled,单败不拦整批,成功单按仓写 wms_carrier_handovers 凭证。响应 `{handed_over[], failed[]}`;failed 条目含 `code`(REQ-20261102-30 增,稳定枚举:ALREADY_HANDED_OVER/NOT_PACKED/IN_PROGRESS/ALREADY_FINISHED/BEING_PICKED/NOT_IN_LOAD/CUSTOMS_HOLD/ON_HOLD/NO_PICK_RECORD/SHORTAGE/SHORT_NOT_ALLOWED/SHORT_REASON_INVALID/NOT_FOUND/FAILED,服务端按错误 details 细分、非整表映射,客户端按 code 映射六语、error 英文字段保留兼容)+可选 `status`/`shortage`/`shortages[]`(shortages 条目 2026-11-03 起增 `sku`,供缺货确认卡指名缺哪个 SKU,REQ-20261103-14)。防重复提交:逐单先原子认领(条件 UPDATE handover_claimed_at,仅 status='packed' 且认领为空/过期 2 分钟才成功,migration 779;失败释放、成功保留),同批并发/重复提交每单只处理一次、不双扣;认领列缺失时降级无认领旧行为并记日志。残余风险:认领 TTL 是中断假设——单笔处理超 2 分钟仍未结束时认领可被抢占而 ship core 翻状态无第二道 CAS,理论上仍可双处理(单笔正常秒级,根治项=core 翻状态加 status 条件 CAS,已登记后续)。缺货:deduct 恒 allowShort 构建,未确认时缺货单回 SHORTAGE+shortages 明细供双端确认卡,带 confirm_shortage+shortage_reason 重调走 short 流程(Andy 2026-10-14 口径)。权限 wms.outbound.edit+assertDataScope 逐单(仓/货主)。场景 RG-1249–RG-1252。

POST/api/wms/shipments/{id}/pickup-code-resend

二期交接证据(REQ-20261031-28):重发提货码(换新码、计数+1、重新通知;不重置输错、不解锁定)。仅待取态且档位需码。错误:`PICKUP_NOT_READY`、`PICKUP_CODE_NOT_REQUIRED`(无证据行=历史单)、`WMS_STATE_001`(简易档)。留痕 `wms.shipment.pickup_code_resent`。

POST/api/wms/shipments/{id}/pickup-code-unlock

二期交接证据(REQ-20261031-28):主管重置提货码。body `{supervisor_id*, supervisor_password*}`,三件套与 OMS 同码同配方(共享件 supervisor-approval);成功清零 attempts、解锁定、换新码并通知,未锁定态亦可执行(受控换码)。错误:`SUPERVISOR_REQUIRED`/`SUPERVISOR_SELF`/`SUPERVISOR_NOT_ELIGIBLE`/`SUPERVISOR_PASSWORD_INVALID`、`PICKUP_NOT_READY`、`PICKUP_CODE_NOT_REQUIRED`。留痕 `wms.shipment.pickup_code_unlocked`。

GET/api/wms/shipments/{id}/freight-summary

出货三方式(REQ-20261025-03 / D20 §3.2):freight 托盘自动汇总(唯一读口)。托盘集=本单直挂托盘 ∪ 本单 pick 行 picked_to_pallet_id;逐托回 {lpn, pallet_no, weight_kg, weight_estimated, 尺寸, volume_cbm, measure_source, items}+{pallet_count, total_weight_kg, total_volume_cbm, dims_missing_count, suggested_freight_class, freight_class(已确认值)}。无实测重时按托盘行×产品单重估算并惰性回填(measure_source=auto,只填空值;实测值不被覆盖)。559 未应用回空汇总+`not_ready: true`(不报错)。

PATCH/api/wms/shipments/{id}/freight

出货三方式(REQ-20261025-03):freight 数据录入。body `{carrier?, pro_no?, carrier_pickup_time?, appointment_time?, freight_term?, freight_class?, pallets?: [{lpn?, gross_weight_kg?, length_cm?, width_cm?, height_cm?, measure_source?}], write_back_item_dims?}`;头字段传了才改,逐托按 (org, shipment, lpn) 先查后写(既有 measured 不被 manual/auto 覆盖;新建托 status=staged、source_type=pick),单品托可回写产品主数据空值列。返回 freight-summary 同形。

GET/api/wms/shipments/{id}/bol-data

出货三方式(REQ-20261025-03):BOL 结构化数据。返回既有 VICS BOL 契约(buildShipmentBol)+freight_summary+freight_class(人工确认值优先,否则密度建议值并标 `suggested: true`);确认后托盘带毛重时 totals 用逐托毛重汇总。BOL 门(D65):order_type 非 freight(含 parcel 与 will_call)回 `BOL_FREIGHT_ONLY`。

GET/api/wms/shipments/{id}/bol

取出库单级 BOL:已在 Load 中则返回其 Load 的 BOL,未入 Load 按出库单单独生成;仅限整车(parcel 单直接 409)。

POST/api/wms/shipments/{id}/commit

出库单提交:draft→commit 并锁库存(可用量转已分配);已是 commit 幂等直接返回。OMS 推送的单生而为 commit,本接口主要给 WMS 手工建单用。

GET/api/wms/shipments/{id}/deduct-options

Direct Ship 扣减候选(2026-10-22 Outbound 一期):按出库单行返回可扣库位候选,**按 location 聚合**(同库位多货主合并:qty_on_hand/qty_available 求和、qty_allocated_for_this_order=本单在该库位的已分配量、pallets 按托盘去重合并)。排序:qty_allocated_for_this_order 降序(分配腿优先)→ qty_available 降序,lot 效期 FIFO。行含 location_type/zone/pallet_required(storage 类库位必扫/选托盘);响应 `{shipment_id, lot_truncated, items:[{shipment_line_id, item_id, ordered_qty, shipped_qty, lines:[...]}]}`,lot_truncated 为分页取全实测值。权限 `wms.outbound.view` + assertDataScope。

POST/api/wms/shipments/{id}/deliver

送达确认:shipped→delivered(终态);签收人/POD 可后补(API 接受并回显,持久化列待补);只更新 OMS 内部状态,不触发渠道回传。

POST/api/wms/shipments/{id}/hold

单据 Hold(2026-10-20,migration 491):body `{reason_code, note?}`,只动 WMS 本地位(hold_local)。Hold 拦:建 pick task(generate/zone/cluster/wave 全部路径,失败原因码 ON_HOLD)、ship(wms-ship-core 入口,含 handover/Load 关闭)、pack-confirm、改量(PATCH lines/warehouse)。pick task 已存在时不取消任务,start-picking/pick-confirm 不拦(拣货是仓内可逆移动,靠 pack/ship 门兜底)。原因走主数据 category=`order_hold`。错误码:ORDER_ON_HOLD / ORDER_ALREADY_ON_HOLD / ORDER_NOT_ON_HOLD / ORDER_HELD_BY_OMS(只有 OMS 传导 Hold 时本地 unhold)/ WMS_STATE_001(终态单据)/ HOLD_REASON_*。关联端点 `/api/wms/shipments/{id}/unhold` 同体(响应含 still_on_hold 表示 OMS 传导仍在)。

POST/api/wms/shipments/{id}/carrier-change

Order 级承运商/服务受控变更(2026-10-27,REQ-20261027-15):body `{carrier*, service_type?, reason_code*, note?}`。承运商/服务是出库单级属性——更新 `wms_shipments.carrier/service_type`,整单包裹即时跟随(包裹打单只读订单级或 RS 选价,见 rate-selection)。原因必选:走主数据 `shared_reason_codes` category=`carrier_change`(种子在 REASON_CODE_DEFAULTS,Master Data 原因码页可维护;服务端校验:组织表有行按表、无行回退种子)。终态(fulfilled/delivered/closed/cancelled)拒绝 → WMS_STATE_001;缺 carrier/reason 或原因不在类别内 → WMS_VALID_001。留痕:`wms_audit_log`(action=`wms.shipment.carrier_changed`,details 含改前/改后 carrier+service、reason_code、note),审计写入失败即整单报错 → WMS_SERVER_001(不静默丢痕)。权限 `wms.outbound.edit`。响应 `{id, shipment_no, carrier, service_type}`。发货台 Order 级「变更/指定承运商」弹窗专用。

POST/api/wms/shipments/{id}/rate-selection

Rate Shopping 包级选价留痕(2026-10-27,REQ-20261027-15):body `{package_no*, carrier*, service?, price*, cheapest_price*, source*: manual\

POST/api/wms/shipments/{id}/pack-confirm

打包确认:picked→packed(Shipping Station pack-verify+打 label 完成后推进);已是 packed 幂等直接返回;有 OMS 订单时镜像 packed 事件。

POST/api/wms/shipments/{id}/pick-confirm

拣货确认:picking→picked(拣货任务完成后推进);已是 picked 幂等直接返回;有 OMS 订单时镜像 picked 事件。

GET/api/wms/shipments/{id}/picked

出库单已拣明细(2026-10-19 新增,出库单详情 Picked Inventories tab)。数据源:`wms_pick_task_lines`(行上直带 `shipment_id`)+ `wms_tasks`;cluster 合并行按 `tote_splits[].{shipment_id,qty,picked_qty}` 展开过滤(防串单)。返回按拣选任务分组:`[{task_id, task_no, pick_method, task_status, lines:[{item_id, sku, item_name, qty_to_pick, qty_picked, location_id, location_code, lot_no, tote_lpn, from_location_id, from_location_code, from_lpn, to_location_id, to_location_code, to_lpn, container_kind}]}]`,按任务创建时间升序;无数据返回 `[]`(meta 含 `shipment_no`)。**拣选四要素(2026-10-23 加,migration 531)**:`from_location_code/from_lpn/to_location_code/to_lpn/container_kind` 为 pick 确认时落行的实测值(来源库位+来源托盘 LPN、落位+目标载具 LPN、载具类型 pallet/tote/wave_pallet);合并行 `to_lpn` 取该单 split 的 license_plate;未记录(存量未回填、picking 位无托盘、直发无落位)为 `null`,前端显示「—」;`from_location_code` 存量未落时回退计划位 `location_code`(执行端强制扫码位=计划位)。权限:`wms.outbound.view`(与出库单详情 GET 一致)。示例:`GET /api/wms/shipments/<uuid>/picked` → `{ok:true,data:[{task_no:"TSK-PICK-7L7E9RBZ",pick_method:"order",task_status:"completed",lines:[{sku:"BB-STR-050",qty_to_pick:119,qty_picked:119,location_code:"BKC-08-35-4",tote_lpn:"LPN-20261017-T01"}]}],meta:{shipment_no:"OO-20261019-0001"}}`。**2026-11-06(REQ-20261106-31)**:lines[] 加法加 `pick_line_id` 与 `serials: string[]`——该已拣行在拣货时采集的序列号(数据源 `wms_pick_sn_log`,双路口径与 /serials 端点一致:`shipment_id` 直查+NULL 行经本单 pick lines 的 `pick_line_id` 兜底,按 pick line 分组一次取齐、无逐行查询;合并行展开段按 `tote_id`/`license_plate` 与 split 精确配对、未配上的余量 SN 归本行末段,绝不跨行);无 SN 的行 `serials: []`。

GET/api/wms/shipments/{id}/putbacks

出库单退回上架历史(2026-10-19 新增,出库单详情 Put Back History tab)。无专门退货记录表:一次退回 = `wms_tasks`(`source='pick_return'`)+ `wms_task_step_log`(step_name='Return to Stock')+ `wms_putaway_task_lines` 拼装;两路(订单级 `return-to-stock` 直接关联 / 任务级经原 pick task 的 lines 反查,cluster 多单串扰按 lines 校验 item)归一按时间倒序。reason 枚举:`task_cancelled`/`order_cancelled`/`wrong_pick`/`wrong_qty`/`other`。返回:`[{task_no, via:'order'\

GET/api/wms/shipments/{id}/serials

出库单序列号(2026-10-19 新增,出库单详情 Shipping SN tab)。⚠️ **口径=拣货采集**:数据源 `wms_pick_sn_log`(拣货扫 SN 写入,直带 `shipment_id`;NULL 行经 `pick_line_id` → `wms_pick_task_lines.shipment_id` 兜底,两路按 log id 去重);ship/pack-confirm 不写 SN,Return to Stock 不回滚——不是"已发运 SN",响应 `note` 固定声明 `Serial numbers shown here were captured during picking. They are not verified at ship time.`。返回 `{note, items:[{serial_no, item_id, sku, task_no, tote_id, lpn, scanned_by, scanned_by_name, created_at}]}`,按采集时间升序;无数据时 `items:[]`。权限:`wms.outbound.view`。

POST/api/wms/shipments/{id}/ship

发运;deduct 行可选 `shipped_weight`(P0 食品/冷链:仅 is_catch_weight=true 的产品生效,写 wms_order_lines.shipped_weight + 台账第二数量(负)+ 扣减重量余额);order_type=parcel 时按 `body.packages[].items[]` 行元素 `custom_fields`(行级 entity=wms_package_line)校验后写入 wms_outbound_shipment_lines,未知 key 丢弃,非法 400

GET/api/wms/shipments/{id}/shipped

出库单发运记录(2026-10-19 新增,出库单详情 Shipped Inventories tab)。数据源:`wms_outbound_shipments`(1 行=1 包裹 parcel / 1 票货运 freight,SP- 编号,关联列 `order_id` 指向本单)+ `wms_outbound_shipment_lines`;parcel 由 ship 接口幂等生成(1 package=1 行),freight 由 Load 关闭生成(1 order=1 行)。返回:`[{id, shipment_no, order_type, carrier, service_type, tracking_number(parcel 用 tracking_number;freight 取 pro_no/bol_no 兜底), package_index, package_total, weight, weight_uom, shipped_at, shipped_by, shipped_by_name, status, lines:[{item_id, sku, qty, lot_no, uom, serials}]}]`,按 package_index/shipped_at 升序。权限:`wms.outbound.view`。**2026-11-06(REQ-20261106-31)**:lines[] 加法加 `serials: string[]`=该包裹行绑定的序列号(`wms_outbound_shipment_lines.serials`,migration 650 打包采集落行);该列经独立守卫查询读取,列缺失(42703/PGRST204)时降级为空数组、端点不报错,其余错误照常上抛。

POST/api/wms/shipments/{id}/start-picking

已于 2026-10-28 随 REQ-20261028-06 下线删除:整单一次性出号、无快照无哈希的旧口径由下方 labels 六动作(ensure-or-reuse+内容快照+内容哈希)替代,不留双轨。历史行为见 git 历史。

GET/api/wms/shipments/{id}/labels

Freight Order 标签总览(REQ-20261028-06):一次返回逐托/逐箱标签状态与三项打印门控,供订单页「托盘与标签」区、头部 Print 下拉、Load 页标签块与 SP 详情 SSCC 清单共用。Freight 判定走 resolveFulfillmentMethod 统一链;非 freight 单快速返回 is_freight=false,不做托盘组装。

POST/api/wms/shipments/{id}/labels/print

生成/取回标签 ZPL(REQ-20261028-06):kind=pallet-standard(仓内标准托标,无 SSCC,仅已封托)/ pallet-ucc(GS1 托盘 UCC)/ carton-ucc(GS1 纸箱 UCC)。UCC 目标走 ensure-or-reuse:已有同内容 active 标签直接复用同号;内容哈希不符的目标进 mismatches 拒绝出 ZPL,调用方确认后带 regenerate_label_id 作废旧标签重生新号;SSCC 首次生成时同刻写内容快照行(wms_ucc_label_contents)。命中多个目标时部分成功不整批失败(逐个进 results/skipped)。

POST/api/wms/shipments/{id}/labels/printed

打印成功回执(REQ-20261028-06):前端逐张经 Device Hub 打印后,只把实际成功的子集回执回来(部分失败靠重打同 ZPL 补打,不重新调 print、不重复生号)。UCC 标签累加 print_count 并写 last_printed_at/by;标准托标按 pallet_ids 回写托盘 label_printed_at/by。幂等可重复提交。

POST/api/wms/shipments/{id}/labels/void

作废一张 active UCC 标签(REQ-20261028-06):置 status='void' 并记 voided_at/by/reason;SSCC 永不复用,重打自动生成新号。订单或所属 Load 已进入终态(fulfilled/delivered/cancelled 等)时拒绝(SHIPMENT_FROZEN)。

POST/api/wms/shipments/{id}/pallets/seal

手动封托(REQ-20261028-06):托盘 building/receiving/staged → closed,写 closed_at/closed_by 并记审计(wms_audit_log)。条件更新(CAS)防并发:状态已被别人改动时回大白话冲突提示。封托后内容冻结(拣选/移库改 closed 托一律被守卫拦下),打印标准托标/UCC 的前置条件。另有两处自动封托:freight 单打包收口、托盘装车。

POST/api/wms/shipments/{id}/pallets/unseal

解封(REQ-20261028-06):原因必填。先把该托 active 的 SSCC 标签逐张作废(原因注明因解封作废),再把托盘置回 staged 并清空 closed_at/closed_by,全程审计留痕。订单/Load 已冻结时拒绝。

POST/api/wms/shipments/{id}/ucc-print

**已下线(2026-10-28,REQ-20261028-06)**:整单一次性出号旧动作删除,由上方 labels 六动作替代(ensure-or-reuse+快照+哈希口径),不留双轨。

GET/api/wms/shipments/{id}/pack-exceptions

打包台异常处置(D58,REQ-20261029-11):本单异常清单,`page`/`page_size` 分页(`.range()`),响应 `{rows,total,page,page_size}`;行=`wms_pack_exceptions` 全字段(类型/状态/原因码/qty_before·after/政策快照/处置留痕)。权限沿 shipments 既有口径+assertDataScope(仓+货主)。

POST/api/wms/shipments/{id}/report-pack-exception

站台上报异常:body `{exception_type*: damage/shortage/overage/wrong_item/lot_mismatch, reason_code*(shared_reason_codes category=pack_exception), item_id*, serial_no?, lot_no?, qty?, shipment_line_id?, package_ref?, freeze_same_lot?(错 lot 默认 true), shortage_line_id?(错拣联动报缺)}`。服务端复核 SN 归属(须属本单已拣集);同 (org, shipment_id, serial_no, type) 有未关闭行时幂等返回既有行。报损当刻落账(SN→damaged+台账+实物去损坏区库位);报缺先进 pending_verify 不减量;多拣/错拣生成上架任务(source=station_overage)。

POST/api/wms/shipments/{id}/resolve-pack-exception

异常处置推进(状态机校验,非法迁移 409 大白话):body `{exception_id*, action*: found/confirm_lost/reverse_lost/release_hold/label_resolved/force_close/resend_oms_notify, supervisor_pin?, note?}`。found=报缺找回(打包员可);confirm_lost/reverse_lost/release_hold/force_close=主管动作(PIN+原因必填),confirm_lost 核销后进余量分岔单点(补拣/三态政策);reverse_lost=撤销确认丢失(回滚核销、异常退回待核实,已减量发运/补拣完成的拒绝并给出路);release_hold 只释放 hold_origin=pack_exception 的整单拦截且执行前复核缺口达标、未达标拒绝;resend_oms_notify 补发减量通知(异常行 oms_notified_at 留痕)。

POST/api/wms/shipments/{id}/pack-exception-override

主管改判/放行:body `{exception_id*, action*: weight_override/policy_override, supervisor_pin*, note*, policy?(policy_override 必填,三态之一)}`。weight_override 把称重拦截置 overridden 留痕(两次重量+放行人);policy_override 对单个未结异常改判余量政策(必填原因,写入 resolution_detail+政策快照不回溯在途单据)。打包员调用被拒。

POST/api/wms/shipments/{id}/report-label-block

站台买单失败回写:body `{message?(承运商原始错误), package_ref?}`。服务端按错误映射数据(`apps/wms/lib/pack-station-rules.ts` LABEL_ERROR_RULES)分类 address_rejected/service_unavailable/account_rate_error/carrier_other,自动生成 label_block 异常(status=blocked)进受阻队列;修复后用 resolve 的 label_resolved 关闭,重新买单走既有买单幂等(包裹不拆、SN 不重扫)。

波次/api/wms/waveGETPOSTPATCHDELETE24 个接口

GET/api/wms/wave/cutoff-times

截单时间列表:按货主/承运商模糊筛,默认只返回启用的(传 is_active=false 查全部),分页。

POST/api/wms/wave/cutoff-times

新建截单时间:client_id+截单时间必填,时间格式 HH:MM。

DELETE/api/wms/wave/cutoff-times/{id}

删除截单时间(硬删)。

GET/api/wms/wave/cutoff-times/{id}

单个截单时间详情。

PATCH/api/wms/wave/cutoff-times/{id}

编辑截单时间:所有字段可选;client_id 变化时校验归属;时间 HH:MM。

GET/api/wms/wave/dispatch

Dispatch 预览(不建波次):按货主查其 dispatch setting,返回每 setting 的命中单数+按货主×筛选器分组明细,供手动释放页表格/展开行展示。**附加模式(2026-10-21)**:传 orders_for=<setting_id> 时改为返回该 setting 当前命中的订单明细分页(Release Waves 页 Order Qty 弹窗),求值与 preview 完全同源(lib/wave-dispatch 的 collectPreviewIds),与 Order Qty 数字一致;属性快捷筛选参数同 preview 口径。

POST/api/wms/wave/dispatch

手动释放波次:逐 setting 调 dispatch(匹配订单→切块→建 released 波次→写 log),逐 setting 独立汇总成败(单个 setting 失败不影响其余、不整次 500)。2026-10-21 起:每个 wave 同步建 pick task 并按 pick-tasks/generate 同口径写 `wms_pick_task_lines` 明细行(分配库位+seq+生成日志),回写出库单 `pick_task_id`/`pick_task_no`;某个 chunk 建不出明细行(无订单行/已拣完/整块零可分配库存,或规则 W-K-H6 `allow_short_pick=false` 且缺货)时只跳过该 chunk——刚建的 wave 与 pick task 置 cancelled、明细行删除、出库单 pick_task 回写清除,出库单不被锁定(状态保持 draft/allocated,可被下一次 dispatch 再次命中),同时写一条 status='failed' 的 dispatch log 并把原因记入该 setting summary 的 skipped;其余 chunk/setting 照常放行。部分缺货(允许短拣时)以 partial log 留痕。修复前建的存量 wave 任务无明细行(桌面建议路线为空、手机 Start 报无明细),不做数据回填。

GET/api/wms/wave/dispatch-logs

Dispatch 执行记录(手动/排程的跑批日志,附波次号与货主/setting 名,排查用;按创建时间倒序,分页)。每行附 tasks[](2026-10-21 加法字段):该 wave 实际生成的 pick task(真实关联 wms_tasks.source_doc_type='wave' AND source_doc_id=wave_id,按创建时间升序;无 task 为空数组),Release Waves 页 Log 表 Task 列据此跳转 /wms/tasks/{id}。2026-10-22 Wave auto 一期加法(migration 507):响应行新增 task_id / assignment_outcome / assignee_id 三字段——结构化指派结果,仅该 chunk 的 success 行有值(一任务恰一行),其余行 null;assignment_outcome 枚举:assigned_auto / assigned_fallback / assigned_dedicated / unassigned_not_configured / unassigned_no_candidate / unassigned_dedicated_unresolved / unassigned_error;新增同名筛选 query 参数(传 'unassigned' = 全部未指派结果)。按 outcome 统计时只计 task_id 非空行。

GET/api/wms/wave/dispatch-settings

Dispatch Setting 列表:按名称模糊/货主(customer_filters 内含)/筛选器筛,分页。is_active 口径:默认只返回启用的(不传或 is_active=true);is_active=false 只返回停用的;传 is_active=all 不按状态过滤(全部)。(2026-10-21 修复:filter_id 分支此前把 JS 数组传给 jsonb 列的 contains,PostgREST 报 invalid input syntax for type json、该参数一查就 500,已改传 JSON 文本。)

POST/api/wms/wave/dispatch-settings

新建 Dispatch Setting:name 必填;默认拣选方式 order/cluster/wave/wave_by_item;任务优先级 low/medium/high/urgent。

DELETE/api/wms/wave/dispatch-settings/{id}

删除 Dispatch Setting(硬删;被 scheduler 引用的 setting 删除后 scheduler 需人工清理)。

GET/api/wms/wave/dispatch-settings/{id}

单个 Dispatch Setting 详情。

PATCH/api/wms/wave/dispatch-settings/{id}

编辑 Dispatch Setting:所有字段可选;customer_filters/secondary_filters 传数组整体替换;default_pick_method/task_priority 做枚举校验;client_id 逐个校验归属。

GET/api/wms/wave/filters

Order Filter 预设列表(名称模糊搜,分页;conditions 直接返回,供列表页「Selected Fields」列展示字段 pill)。**Wave Filter 扩展(2026-10-19)**:conditions 新增 9 个 Order Attributes 字段(filter 条件 key → `wms_shipments` 派生列),均为 boolean,operator 用 eq/ne:`single_unit`→`is_single_unit`(单件单)、`international`→`is_international`(国际单)、`repack_required`→`needs_repack`(需重新包装)、`hazmat`→`has_hazmat`(含锂电/危险品)、`temp_control`→`needs_temp_control`(需温控)、`serial_capture`→`needs_serial_capture`(需采集序列号)、`batch_tracking`→`needs_batch_tracking`(需批次追踪)、`oversize`→`is_oversize`(超大件单)、`gift`→`is_gift`(礼品单)。字段映射在 `lib/wave-dispatch.ts` 的 `FIELD_COLUMN`,求值与其它 conditions 同口径。**注意**:filter 条件的字段 key 是 `international`,不是 `is_international`——`is_international` 只是 Release Waves dispatch 接口(`GET/POST /api/wms/wave/dispatch`)的快捷参数名,在 conditions 里传 `field: 'is_international'` 会被判 unsupported field 而报错。另 `conditions` 支持 `cf:<field_key>`(自定义字段,实体 `wms_outbound_order`)。**出库单状态归一化**:`SHIPMENT_STATUS_ALIASES` 在 evaluate/filter 两路均应用(commit→allocated、ready→planned(migration 472 存量清理后遗留别名)、shipped→fulfilled),未知状态值跳过+warn 不崩溃。

POST/api/wms/wave/filters

新建 Order Filter:name 必填;conditions 至少选一个过滤字段;operator 取值 in/not_in/eq/ne/gt/lt/gte/lte。

DELETE/api/wms/wave/filters/{id}

删除 Order Filter(硬删除,仅限本组织)。

GET/api/wms/wave/filters/{id}

单个 Order Filter 详情(含 conditions 全量,编辑弹窗用)。

PATCH/api/wms/wave/filters/{id}

编辑 Order Filter:name/warehouse_id/conditions/is_active 按需部分更新;conditions 传入时整数组替换。

POST/api/wms/wave/scheduler/run

Scheduler 跑批入口(cron 用):双模式——带 x-cron-secret 请求头时遍历所有组织(绕过登录,cron 定时跑),已登录用户直接 POST 只跑本组织;命中的排程逐 setting 释放波次并更新 last_run_at。

GET/api/wms/wave/schedulers

Wave Scheduler 列表:按名称模糊/货主筛,分页。

POST/api/wms/wave/schedulers

新建 Scheduler:name+dispatch_setting_ids 必填;work_days 默认周一到周五;time_from/time_to(HH:MM,可空=全天);step_minutes 默认 30。

DELETE/api/wms/wave/schedulers/{id}

删除 Scheduler。

GET/api/wms/wave/schedulers/{id}

Scheduler 详情。

PATCH/api/wms/wave/schedulers/{id}

更新 Scheduler(部分字段)。

拣选任务/api/wms/pick-tasksGETPOST12 个接口

GET/api/wms/pick-tasks/{id}

查拣选任务详情:任务全字段 + 明细行(库位 code、商品 SKU/名称)。

POST/api/wms/pick-tasks/{id}/complete

完成拣选任务:全部明细行须已拣(picked)或已短拣(short);回写出库单 picked_qty、推进出库单 picking→picked/staged、触发补货检查;支持强制关闭(剩余 pending 行按已拣量标 short,须选原因码)。

POST/api/wms/pick-tasks/{id}/pick

拣选确认(手机端扫码核心):扫库位+扫商品+输数量+放入容器,一次提交一个 step;支持 client_step_key 幂等防重扣,部分拣选自动拆出剩余量新 step 排队尾。面向用户报错(含 tote_link 占用拦截、混托警告 `pallet_mixed_warning`)按请求 lang 本地化:`?lang=` → `x-lang` 头 → `Accept-Language` → 默认 en,六语 en/zh/es/pt/fr/ja(`lib/pick-messages.ts`,REQ-20261102-16);错误码与 HTTP 状态不随语言变化。

POST/api/wms/pick-tasks/{id}/bind-cart

Cluster 拣选任务绑车(手机端扫车绑定):把一辆拣选车绑到任务上,按单分配 tote 并填充各行 tote_splits,任务转 in_progress、出库单转 picking。选格口径(REQ-20261102-16):候选 tote 须 status='idle' **且** 未被真实占用——tote 最新 tote_link 挂着本任务之外未终态出库单的视为被占、不分配(判定与 pick 路由 tote_link 拦截同源:`lib/wms-station.ts` findLatestLink/findLinkBlockers);真空不足且存在被占 tote 时硬失败点名,不再软返回。报错按请求 lang 本地化(同 pick:`?lang=` → x-lang → Accept-Language → en,六语)。

POST/api/wms/pick-tasks/{id}/short

短拣上报:某明细行拣不到足量时,按当前已拣量标 short(缺货/破损等),任务可继续完成,剩余量后续可重新生成拣选任务。

GET/api/wms/pick-tasks/{id}/sn-log

拣货 SN 续扫查询:track_serial 行已扫 SN 列表与待扫量(REQ-20261023-61)。鉴权:组织成员(withWms)。

POST/api/wms/pick-tasks/{id}/sn-log

拣货 SN 扫码登记:track_serial 行确认前 SN 采集门(SN 门禁认 track_serial 双列 OR)。鉴权:组织成员(withWms)。REQ-20261023-61。

POST/api/wms/pick-tasks/{id}/start

开始拣选:盘点锁定校验,任务 pending/assigned → in_progress,关联出库单 → picking。

POST/api/wms/pick-tasks/generate

从出库单生成拣选任务:draft 单自动锁库存转 allocated,按拣选规则分配拣货库位、按拣货路径排序明细行;支持 order/cluster/wave/wave_by_item 和分区约束。

POST/api/wms/pick-tasks/zone-precheck

Zone Pick 预检:给定一批出库单,查每单的货落在哪些 Zone、有没有缺货、要不要拆单。桌面端预检向导的数据源——"先看清楚再动手",实际分配以 zone-generate 为准。

POST/api/wms/pick-tasks/zone-generate

按 zone 拆分生成拣选任务:一 zone 一 task,有货的 zone 才建;urgent 单单独建 task;单 zone tote 需求超最大车格数时拆成 2 个 task。同时创建和单 batch 并记每单应到 tote 数。picker 默认按 zone 绑定自动指派(同区多人按手头未完成任务数最少分),可手工覆盖。

POST/api/wms/pick-tasks/zone-autoplan

Zone Picking 自动成批(2026-10-24,REQ-20261023-12):执行 Task Rules 的 Z1/Z2 政策——按仓扫描候选出库单(状态 draft/allocated、未 Hold、小包裹、无未完成拣选任务、只读探量确认有货且至少有在册 zone 分量),按 zone 汇总;某 zone 命中触发(Z3 豁免开启时有加急单 / 单数 ≥ Z1 `min_orders` / 最老单等待 ≥ Z2 `max_wait_hours`)后,生成集合只取触碰已触发 zone 的单(review P2 裁定 (b) 定版:未触发 zone 的单不提前生成;跨 zone 单整单生成;zone_scope 恒 all)送进与手工相同的生成核心(`zone-generate` 同一实现)建 batch+任务。定时任务 `wms-zone-pick-planner` 周期性全组织调用同一引擎(调度挂载在平台 cron.d,建议 15 分钟一轮;单仓单轮上限 200 单)。

装车单/api/wms/loadsGETPOSTPUTPATCHDELETE21 个接口

DELETE/api/wms/loads

批量删除装车单(只有 new/cancelled 状态可删,不符合状态的整批报 400)

GET/api/wms/loads

查询装车单(Load)列表,支持仓库/状态/类型/承运商/客户/循环取货路线/预约时间筛选,每行附关联出库单数和首单信息

POST/api/wms/loads

创建装车单(Build Load):load_uid 系统自动生成,至少关联 1 个出库单(cross dock 空车可无单);Load No 业务编号同组织查重

GET/api/wms/loads/{id}

查 Load 详情:表头全字段、按 sequence 排序的 order_lines、装车任务扫码进度、BOLD 打印标记和 Milk Run 路线。2026-11-04(REQ-20261104-39)加法字段 `cross_dock_tasks`:挂本 load 的越库装车任务(wms_cross_dock_tasks,task_type=shipping)摘要数组,供 Load 详情页「Load task」卡与标准装车任务并列呈现(展示层合并读,任务头并表归 D109);`task` 字段口径不变。

GET/api/wms/loads/{id}/bol

按 Load 数据生成标准 VICS BOL(数据+纯文本打印视图),打印即记"打印 BOL"步骤日志(Load 关闭前置)。2026-10-21 加 `scope` 三选项 + 双签字/实装口径:明细在任务已扫码时按实装托盘汇总;BolData 新增 `master_bol_no` 与双签字字段(shipper_name/carrier_name/签名图链接/signed_at)。

PATCH/api/wms/loads/{id}

更新 Load:表头字段(发运/送达后不可改)、状态流转(new→planned→loading;new/planned→cancelled)、order_lines 全量替换(仅 new)。

GET/api/wms/loads/{id}/bol

按 Load 数据生成标准 VICS BOL(数据+纯文本打印视图),打印即记"打印 BOL"步骤日志(Load 关闭前置)。2026-10-21 加 `scope` 三选项 + 双签字/实装口径:明细在任务已扫码时按实装托盘汇总;BolData 新增 `master_bol_no` 与双签字字段(shipper_name/carrier_name/签名图链接/signed_at)。

POST/api/wms/loads/{id}/clone

克隆 Load(2026-10-18):以源单为模板新建一张 Load——复制 `wms_loads` 单头行全部字段,仅剔除 id / load_uid / created_at / updated_at / created_by,生成新单号 load_uid(LOAD 前缀全局原子序号,形态 LOAD-000001,经 genDocNo),status 强制置 draft,organization_id 置为调用方组织。注意(按实现):仅复制单头行,关联明细(load 与出库单的关联、destinations 明细)不随克隆复制,新单为无明细的 draft。无请求 body。错误:源单在本组织不存在 → 404 `WMS_NOT_FOUND_001`;查询/插入失败 → 500 `WMS_SERVER_001`(插入失败 message 为 "Failed to clone load")。

POST/api/wms/loads/{id}/close

Load 关闭发车:校验全部托盘已扫码装车且已打印 BOL,仓库与司机双签字后 Load 置 shipped,关联出库单同步发运并自动生成货运单。2026-10-21:扫码完整性校验取并集——旧 step log「装车扫码」∪ 新通道 wms_load_task_scans(按任务行 pallet_id 对账)。发运扣减按每单的 pick 台账正腿落点计算(实际出运托盘 × 拣入量),任务期望托盘集合同口径,均不含拣选来源托盘。

DELETE/api/wms/loads/{id}/destinations

从 Load 移除一个目的地;删空后 is_multi_destination 自动回 false。

GET/api/wms/loads/{id}/destinations

查 Load 的多目的地列表(按 sequence 排序,含目的地详情),Cross Dock 一车多卸点场景用。

POST/api/wms/loads/{id}/destinations

给 Cross Dock Load 加一个卸货目的地(仅 cross_dock Load、未完结状态可操作)。

PUT/api/wms/loads/{id}/destinations

替换主目的地 { new_destination_id*, reason* }(2026-11-06 新增,REQ-20261106-21):单目的地车整体替换;多目的地车只替换 sequence 首行停靠点,其余停靠点不动。原因必填;同步未完结(open/in_progress)发运任务的目的地快照(响应 `synced_tasks`);留痕 wms_load_destination_history

PATCH/api/wms/loads/{id}/destinations

停靠点调序 { items: [{ destination_id, sequence }]*, reason* }(2026-11-06 新增,REQ-20261106-21):items 必须与现停靠点集合完全一致;只对 sequence 真变的行留痕;表头主目的地按新 sequence=最小行再同步

POST/api/wms/loads/{id}/load-scan

手机端逐托盘扫 LPN 确认装车:记扫码日志、托盘置 loaded;首次扫码 Load 进 loading,全部扫完装车任务自动完成。2026-10-21:加顺序校验(按任务行 seq_no 分组算当前出库单,扫后面的单 → `LPN_WRONG_ORDER_SEQUENCE`,文案点名当前单与还差几托)+ 响应 `data.progress { orders[], current_shipment_id, scanned, total }`。

DELETE/api/wms/loads/{id}/shipments

从 Load 移除一个出库单:仅 new/planned 状态;该单已生成装车任务行时须先删任务。

POST/api/wms/loads/{id}/shipments

向 Load 追加一个出库单:仅 ltl/ftl 单,Load 须为 new/planned 状态。

GET/api/wms/loads/{id}/task

查 Load 的装车任务及任务行:托盘 LPN/出库单/是否已扫码装车。

POST/api/wms/loads/{id}/task

生成/重新生成装车任务:任务行=各关联出库单的实际出运托盘(pick 台账正腿落点,不含拣选来源托盘),按出库单编装车顺序;每单无出运托盘时报错。

POST/api/wms/loads/import

批量导入 Load(前端已解析的 CSV 行):首行 LOAD 表头建单、后续 ORDER 行关联出库单;逐组校验,任一校验失败整组不建单。

GET/api/wms/loads/search-orders

搜可加入 Load 的出库单:限 LTL/FTL、排除已发运/已取消、排除已被其他 open Load 占用的,供 Add Order Lines 弹窗。

装车任务/api/wms/load-tasksGETPOST8 个接口

POST/api/wms/load-tasks/generate

按 Load 生成装车任务与期望托盘清单(wms_load_task_lines 每托一行;LIFO 在此按 stop 序倒序现算)

GET/api/wms/load-tasks/{id}/progress

装车任务进度(服务端原生形状):逐单期望/已扫/缺失/剩余 + 当前应扫 order(milk run 按 stop 倒序 LIFO;无 milk run 按 Load 内 sequence)。2026-10-21 纯加法扩展 steps/photos/load_detail 等段,老字段不变。

POST/api/wms/load-tasks/{id}/progress

Short close——Step 1 未扫齐关闭:必选原因码(category=`load_short`),逐单差异记 step log「装车扫码关闭」(exception),未装托盘保持 staged。

POST/api/wms/load-tasks/{id}/scan-lpn

扫 LPN 装车(wms_load_task_scans 记账,托盘→loaded)。顺序强制(milk run LIFO / Load 内 sequence)。2026-10-21 新增:托盘属已装完的单 → `LPN_ORDER_DONE`;托盘状态 loaded/shipped/missing/closed → `LPN_PALLET_BLOCKED`(文案带现状标签,六语)

POST/api/wms/load-tasks/{id}/photos

Load Task 拍照/签字图上传:文件进统一文档中心,wms_task_photos 存文档 ID(caption=kind),step log 记「装车照片」。

POST/api/wms/load-tasks/{id}/step1

双口径端点。旧口径 `{ info?, photos? }` 记「装车信息采集」(兼容)。新口径 Collect Data(带三号/签名字段任一):校验后三号+双签字回写 wms_loads 现有列,payload 记「装车数据采集」。

POST/api/wms/load-tasks/{id}/report-missing

逐托丢失上报(原因码 category=`pallet_missing` + 主管 PIN;托盘→missing 并自动生成盘点任务)

POST/api/wms/load-tasks/{id}/complete

关闭装车任务(扫齐或 missing 覆盖才放行)。2026-10-21:已做 Short close 且差异覆盖当前剩余数 → 带 exception 标记放行(响应 `exception: true`)

发运清单/api/wms/manifestsGETPOSTPATCH4 个接口

GET/api/wms/manifests

查询日终 Manifest(End of Day 交接单)列表,支持仓库/日期/状态筛选

POST/api/wms/manifests

生成当日日终 Manifest(汇总今日该承运商所有已发货包裹的 tracking 号去重清单;承运商必须配置了 supports_manifest)

GET/api/wms/manifests/{id}

查交接清单(manifest)详情全字段。

PATCH/api/wms/manifests/{id}

manifest 打印打标或交接确认:print 记打印时间;handover 确认交接——除标 manifest handed_over 外,清单内仍 packed/staged 的出库单逐单翻 fulfilled(与手机承运商交接共用发运核心),逐单结果落 handover_result 快照。首次须填交接人;部分单失败照常标交接(失败单留原状态、详情可见);已 handed_over 再调 handover = 重试模式(只处理未翻单,不需再填交接人,attempts+1)。

打包与面单113 个接口

打包台/api/wms/shipping-stationGETPOST12 个接口

POST/api/wms/shipping-station/gift-card

按货主礼品卡配置生成打印内容:separate_card 返回独立卡片 HTML,on_packing_slip 返回标记由前端并入装箱单渲染。

POST/api/wms/shipping-station/label

生成小包裹 shipping label;原包装出一 unit 一包裹,Repack 需指定包装材料并计入包材重量尺寸。REQ-20261028-03:面单 step log 记录补来源契约字段 `label_source='local'`(打包台面单恒本地生成)+`carrier_account_id`(生成时所用账号,void 分发判定依据);已收口锁定守卫——订单 status 为 packed/fulfilled/shipped 或已有 SP 包裹行时拒绝再出面单(`WMS_STATE_001`,`details.reason='order_locked'`),改包裹须先 Void 回退。REQ-20261029-38(修订恒本地口径):订单指定承运商映射到已集成承运商(UPS/FedEx)时,服务端解析该承运商 connected 账号并直连买单——响应 `label_source='carrier_api'`、真承运商 tracking、`zpl=''`、附 `label_base64`/`label_format`(GIF/PDF 图片面单)与 `carrier_test_mode`/`carrier_mock` 如实标注,step log 记录同字段+`carrier_shipment_id`(作废透传);无 connected 账号/指定服务未在账号启用清单/地址不全/买单失败时回 `WMS_VALID_001`+`details.reason`(carrier_account_missing/carrier_service_missing/carrier_service_not_enabled/carrier_address_incomplete/carrier_buy_failed)点名报错,绝不回落本地面单;买单带服务端幂等——同包裹已有 live carrier_api 面单时回既有记录零新购,若订单已改服务而旧面单未作废(记录服务与本次指定服务归一比对不一致)回 `WMS_VALID_001`+`details.reason='carrier_service_changed_label_live'`(details 含 service/existing_service/tracking_number)点名拦截,须先作废旧面单;非集成承运商维持本地生成(`label_source='local'`+TRK- 号+ZPL)。REQ-20261030-41(修订图片面单口径):承运商买单改要热敏格式(UPS 请求 ZPL、FedEx 请求 ZPLII)——承运商回 ZPL 且解码校验(^XA)通过时,响应 `zpl` 为该 ZPL 原文、不带 `label_base64`,step log 记录另落 `label_zpl`(幂等重演与重打优先回原 ZPL 走 Device Hub 直打);承运商没给 ZPL(mock/忽略格式)时才回落 `label_base64`/`label_format` 图片面单(前端开新标签页并自动唤起浏览器打印对话框,尾注如实区分通道)。买单失败的 `details` 另带 `carrier_reason`(承运商失败码)与 `detail`(承运商原始错误摘录,只供异常登记/分类,不上屏)。REQ-20261104-05(D108 G1)增补:出单前先经判定前置件(`lib/wms-label-station.createPackStationLabel`,与 wave-bulk-label 端点共用)——live 面单先行复用后走来源判定单点 `resolveLabelSource`;订单有 active 客供面单附件时走附件路:跳过买单、取附件原文件叠印包裹序回 `label_base64`+`label_format='pdf'`(`zpl=''`),响应 `label_source='attachment'` 并带 `attachment_id`,step log `payload.label` 落五件契约(label_source/attachment_id/tracking_number/carrier/package_no)+billing 子对象,计费同费目 `WMS-LABEL`(`source_module='wms_shipping_station'`、source ref=shipment id+package_no、once 幂等),OMS 回写沿 D64 §13 Q6;附件文件取不到回 `WMS_STATE_001`+`details.reason='label_attachment_unavailable'` 硬拦(不静默回落买单),仅当请求带 `label_attachment_fallback=true`(操作员显式选择)才放行买单并补 step log 留痕;真判渠道取件(channel)时打包台一期不消费、回落买单并在响应 `label_note` 带一行注记,原附件已作废无新 active 时同带作废注记。

POST/api/wms/shipping-station/label/void

作废一张面单(append step log 留痕,不删原记录)。打包台 v2 回退语义:订单 status='packed' 且被作废 tracking 命中任一 parcel SP 行、且作废后有效 SP 数(tracking 未出现在 void step log 中)少于 SP 总数时——先删除该单全部 parcel SP 行及其明细行(两步都查 error 并 GET 复核,失败回 `details.reason='sp_delete_failed'` 不回退、可重试)、再订单 CAS 回 `packing`(清 packed_at/packed_by)、追加 step log 并写打包日志 `order_pack_reverted`;非 packed 状态只留痕不回退;同一 tracking 重复 void 返回 `already_voided` 幂等成功、不重复留痕。v2 窄修 F4 守卫:packed 单的 tracking 已被 `handed_over` 的 manifest 快照(`wms_manifests.tracking_numbers`)覆盖时不留痕、不回退、不删 SP,回错误信封 `details.reason='manifest_handed_over'` 人话;已生成未交接 manifest 的快照不回溯剔除(stale 已知口径,翻单时以 SP/单头为准、无双扣)。REQ-20261028-03 承运商先行:面单创建记录(step log「打印面单」payload)带 `carrier_account_id` 且承运商名映射到已集成 code(ups/fedex)时,先经 `packages/connectors` 的 `upsVoidLabel`/`fedexVoidLabel` 作废(凭证走 shared_carrier_accounts(优先面单记录自带的出单账号 carrier_account_id、无则按 shared 口径取组织内最近可用账号),UPS 无凭证自动 mock(失败注入 env `CARRIER_VOID_MOCK_FAIL`);FedEx 自 REQ-20261028-10 起去 mock,无凭证直接回 FEDEX_KEY_MISSING(映射 unconfigured),不经 mock);承运商成功或回「已作废」才执行本地回退/留痕,留痕与响应带 `void_path='carrier'`+`simulated`;承运商失败则本地零变更(不写 void 留痕、不删 SP、不改状态,仅打包日志记 `label_void_failed`),回 `WMS_CARRIER_001`+`details.reason`(carrier_void_declined/carrier_void_unreachable/carrier_void_unconfigured)。本地号面单/手工 Tracking/未集成承运商走本地路径,留痕标 `void_path='local'`。REQ-20261104-05(D108 G1)增补:面单记录 `label_source='attachment'` 时分类器(`classifyLabel` 第一档,先于承运商硬证据判定)走 attachment 档——不调承运商,只把附件行置 `voided` 释放 tracking 占用(置失败回 `WMS_SERVER_001`+`details.reason='attachment_void_failed'` 且本地零变更),成功后与 local 路同流走 packed 回退/留痕,留痕与响应带 `void_path='attachment'`。

POST/api/wms/shipping-station/wave-bulk-label

Wave 单件批量出库(REQ-20261029-18,设计 `docs/wave-batch-ship-design.md` D63):扫 wave LPN 后对某个 SKU 的剩余单件订单整批出面单。装配经 `lib/wms-wave-bulk.loadWaveBatch`(link 必须为 `wave_pallet_link` 且 pick task `batch_ship=true`,否则 400);剩余=未收口(picking/picked/packing)、无 live 面单(面单记录减已作废集)、行 picked−packed>0,按订单 created_at FIFO;`count` 取窗口(默认全部剩余,单次上限 50,超出由前端按 `remaining_after` 分批续调)。五维门(`evaluateWaveBulkGate`,只判本窗口):内部 carrier+service_type 全一致、产品非 SN、拣选 lot 全同值、尺寸重量齐全(repack 时另须传箱且箱尺寸齐全)、同 VAS 画像(判定接口 `resolveVasProfileKey` 调 D62 `getVasProfile` 取四元组〈action_code/confirm_mode/apply_scope/instruction_text〉`profile_hash` 判全等,无 VAS 配置时恒 'none');门不过回 `WMS_STATE_001`(409)+`details.failures=[{dim, shipment_nos}]`、本批零生成。通过后逐单调 `lib/wms-label-create.createShipmentLabel`(与 label 端点同一实现/同一落账),承运商账号按订单内部承运商名大小写不敏感匹配组织启用账号(同页面 acctForCarrier 口径),每单生成前重查 live 面单(已有则该单回 ok=false 的 order-locked 式结果、不重复生成),逐单 try/catch 隔离失败、全批不回滚。收口仍由打包台既有 pack_finalize 链完成,本端点只生成面单不改订单状态。REQ-20261029-38:逐单结果透传 label 端点同名字段(label_source/label_base64/label_format/carrier_test_mode/carrier_mock)——组内订单指定已集成承运商时同样直连买单,图片面单随结果带出(zpl='' 不算失败)。REQ-20261104-05(D108 G1)修订:逐单改调与 label 端点同一判定前置件(`lib/wms-label-station.createPackStationLabel`),客供面单附件、渠道注记与硬拦口径与 label 端点一致;逐单结果另透传 `attachment_id`/`label_note`,逐单失败另带 `error_reason`(透传错误 `details.reason`,如 `label_attachment_unavailable`,供页面渲染重传/改走买单两动作)。

POST/api/wms/shipping-station/wave-detail

Wave「查看明细」二级入口分页(REQ-20261102-11 / D63 §15,设计 `docs/wave-batch-ship-design.md`):聚合视图之外逐单排查用——按 wave LPN 的 link shipment_ids 服务端分页查 wms_shipments(可选 q 对 shipment_no ilike),对当页单做与 resolve 同口径的轻量富化(明细行+商品 sku/品名/图/track_serial/needs_repack、货主礼品、VAS 画像与日志、DG 空运拦截、service_state 三态、提取后邮编),再以同一纯函数(`apps/wms/lib/wave-aggregate.ts` 的 packingSignatureOf/buildWaveAggregate)给出每行的打包签名与异常种类。鉴权 withWms+assertDataScope(按首行仓/客户范围,与 resolve 同口径);link 不存在回 WMS_NOT_FOUND_001、非 wave_pallet_link 回 WMS_VALID_001(均为人话错误)。查询纪律:`.order('created_at').range()` 分页,`.in()` 当页 ≤50 天然满足分批上限。

POST/api/wms/shipping-station/packing-list

Shipping Station 打印装箱单(Packing List):按出库单解析模板(retailer 专属模板优先,否则默认模板,现行标准版 `default-4x6-V2`),组装变量后渲染 ZPL 返回,由打包台经 Device Hub 打印。模板在 WMS → UCC Templates 维护(template_kind='packing_list')。设计:docs/packing-list-standard.md(D32,REQ-20261026-14)。

POST/api/wms/shipping-station/packing-list-auto

Packing List 自动附带(REQ-20261103-38,设计 docs/packing-list-auto-print-design.md D105)。打包台面单出纸成功后调用,决策单点 lib/pl-auto.ts(路由只装配)。开关维度=client × retailer(表 wms_client_retailer_pl_auto,migration 813;配置面见 retailers/{id}/pl-auto);规格取 retailer 声明 packing_list_media(label_4x6/doc_a4/both,未声明默认 doc);模板走 lib/template-resolve.ts 既有解析链(绑定>专属>标准,platform-follow 在位)。模板内容含 [[PACKAGE_NO]]=逐包模板(按落库包裹 wms_outbound_shipment_lines 只出该包裹行),否则整单版。防重复=wms_pl_auto_prints claim 先占位(唯一索引 org+shipment+scope+COALESCE(package_index,-1)+form):整单版只在第一个包裹触发时出一次、逐包版每包一次;已占位(含 failed)自动链不重试,补打走订单详情手动入口。失败隔离:配置关/已打/无模板/内部异常一律 200 + 空 prints(带 skip_reason/failures),绝不阻塞面单;声明必需却无模板时按既有口径落 missing_template 异常。两个 action:

POST/api/wms/shipping-station/links

补录载具↔出库单关联:tote 必须恰好 1 单且同时置 in_use,pallet 1 单,wave_pallet 可多单;关联记入 task_step_log 可审计。

GET/api/wms/shipping-station/history

Order History 清单(REQ-20261029-10,设计 D57):当前仓库内某日「处理过」的订单,骨架=`wms_packing_logs` 服务端直写的 `order_packed` 事件(按 shipment 去重取最近一次、事件时间倒序),行状态请求时现算五态(packed 已打包待交接/fulfilled 已发运已交接/voided 全部包裹已作废/reverted 已作废·退回打包/packing 打包中),逐包裹内嵌 tracking+承运商/服务+作废标记(作废集与 label/void 同一 step log 事实源,批量对齐)。keyset 游标分页、单日硬顶 500 行(capped=true 提示)。**页面内部接口,不登记为 Agent 工具**(Void 涉钱须人在场)。鉴权 withWms+assertDataScope 仓库范围(与 label/void 同口径)。

POST/api/wms/shipping-station/resolve

扫码调单:依次匹配 tote 箱格条码→托盘 LPN→出库单号→拣货任务号→拣货推车,返回 mode(order 单单/wave 波次/choose 多选)+出库单明细行。REQ-20261028-03:每个 shipment 附带 `packages[]` 包裹回读(SP `wms_outbound_shipments`+明细 `wms_outbound_shipment_lines`;Box/面单来源按 tracking 对齐面单 step log 记录的 `packing_material_id`/`carrier_account_id`,含 `has_label` 标记;无 SP 时为空数组,回读失败降级为空不阻塞调单)。

POST/api/wms/shipping-station/verify

pack-verify 单次扫描解析:先按商品条码/SKU 识别,再按序列号识别;序列号校验是否属于本单商品、是否已发过(已发告警)。

打包录像/api/wms/pack-visionGETPOSTPUTPATCHDELETE44 个接口

GET/api/wms/pack-vision/cameras

打包录像·相机列表(REQ-20261103-11 / D97 §4):本组织相机全量(上限 200、按登记时间倒序),逐行富化 `station_code/station_name/hub_name`(页面拼名用,不露 UUID 拼名)+`rtsp_note`(**2026-11-03 批三-A 起恒为 null**:rtsp 已由 Hub RtspSource 真实支持、原「试点未启用」注记清除,字段保留兼容)。**2026-11-04 REQ-20261104-45 只加字段**:响应增补 `hubs`=本组织全部已配对 device_hubs(上限 200、按 last_heartbeat_at 倒序),逐行 `{id, name, platform, last_heartbeat_at, online}`(online=5 分钟内心跳,与 stations/status 同口径;platform=Hub 所在电脑系统 macos/windows/linux,供下拉在同名多台时区分机器;离线也返回——登记表单 Hub 下拉的第一来源,修「零相机时旧反查来源恒空、第一台相机登记不了」死锁;cameras 字段形状不变)。鉴权:withWms 宽松默认(登录+组织成员;2026-10-07 功能先行口径,权限总开关期),全部查询带 organization_id 隔离

POST/api/wms/pack-vision/cameras

打包录像·登记相机:body `{name*, warehouse_id?, hub_id?, source_type?(uvc 默认/rtsp), source_ref?, station_id?, enabled?(默认 true)}`。name 必填、source_type 只许 uvc/rtsp;warehouse_id/hub_id/station_id 逐个验属本组织(查不到 404 `WMS_NOT_FOUND_001`)+仓库数据范围 assertDataScope。**2026-11-03 批三-A rtsp 口径**:source_type=rtsp 时 source_ref 必填且过地址校验(纯函数 `cameras/rtsp-ref.ts`,与门面 validateRtspSourceRef 同口径)——必须 `rtsp://` 开头、有主机段、无空格、**不许带 userinfo**(authority 段出现 `@` 即账号密码形态),任一不过 400 `WMS_VALID_001` 人话(带账号密码时明示「凭证请到打包台电脑的 Device Hub 里设置,这里只填地址」);rtsp 凭证永不进地址、永不上云端库,只经打包台页 WS 动作 `packvision.set_rtsp_secret/clear_rtsp_secret` 落 Hub 本机保险库(见 D97 §11)。响应 `{camera, rtsp_note}`(rtsp_note 恒 null,见 GET 行注记);错误:400 `WMS_VALID_001`(name 空/source_type 非法/rtsp 地址校验)、404 `WMS_NOT_FOUND_001`、500 `WMS_SERVER_001`(人话+请重试)

PATCH/api/wms/pack-vision/cameras/{id}

打包录像·改相机:可改 `name/warehouse_id/hub_id/source_type/source_ref/station_id/enabled`,warehouse_id/hub_id/station_id 传 null=解绑;改绑目标逐个验属本组织+数据范围(口径同 POST,含 2026-11-03 窄修 P2-2 的 warehouse_id 归属校验);**批三-A 补**:改后最终形态为 rtsp 时同样过 rtsp-ref 地址校验(改类型为 rtsp、或对 rtsp 相机改 source_ref 都按最终形态验,不许绕过 POST 口径);无任何可改字段 400 `WMS_VALID_001`;相机不存在/不属本组织 404 `WMS_NOT_FOUND_001`。响应 `{camera}`(rtsp_note 恒 null,同 GET 行)

POST/api/wms/pack-vision/orders/{orderId}/video/fetch

打包录像·按单调取:对已封箱(closed)窗口逐条建调取请求(Hub 原子领取后拼接窗口时段片段上传成片);幂等——已有 queued/fetching/done 不重复建、failed 可重建;每个纳入窗口写 access_log `fetch`。响应 `{order_id, created, already_requested, open_windows_skipped, note}`(**2026-11-05 REQ-20261105-48 键化**:note 只回键 `submitted/already`、门面按键自备六语)。错误:无窗口 404 `WMS_NOT_FOUND_001`(人话:还没有打包录像记录);只有未封箱窗口 409 `WMS_STATE_001`(人话:还在打包中、封箱后才能调取) **【2026-11-06 本地调取改造注记(REQ-20261106-35/D97 §14,随批一生效)】**:本端点**语义变更**——不再是「调取上传到云端」,改为**建立观看会话**:fetch_requests 新增 `mode`(stream=点播放即建会话看全片/download=下载到本机),会话状态 queued→connecting→active→ended/failed(批一 DB 初始状态 `awaiting_hub`、呈现为排队相位,防旧 Hub 执行器误领走已废止的上传路);`cloud_path` 对视频**停用**(历史行只读);Hub 离线时会话停在排队相位如实呈现、**观看必须等 Hub 在线**,不再承诺上线自动补传;同窗同用户重复建会话复用活跃会话(原幂等口径沿用);access_log 映射随之改:view=播放会话建立、download=下载会话完成**2026-11-07 B1-E 门面口径**:检索页/订单页播放建会话统一传 `mode:'stream'`、详情弹窗下载传 `mode:'download'`(批一只落会话状态机与呈现、真字节链随批三,见 D97 §14.12)

POST/api/wms/pack-vision/sessions/claim

打包录像·Hub 机器通道领取观看/下载会话(批三 v1.2 §B3-3,REQ-20261107-03):原子推进 connecting,响应给齐窗口时段/冻结范围/水印/Hub 中继令牌;中继未开通时 download 不予领取

POST/api/wms/pack-vision/sessions/status

打包录像·Hub 机器通道推进会话状态/进度(批三 v1.2 §B3-3,REQ-20261107-03):active 进度回填(单调)、ended/failed 终态;download/evidence 完成补 access_log

POST/api/wms/pack-vision/orders/{orderId}/video/export

打包录像·导出证据包:前置=全部窗口 fetch 已 done,否则 409 `WMS_STATE_001`+人话提示先点「调取录像」(details 带 windows_not_ready[])。成功回 zip 流(非 JSON 信封):每窗一目录 `window-{shipment_no}/video.mp4`+`keyframe-{open/label/sealed}.jpg`+根目录 `timeline.json`(窗口事件时间线与单据号、导出人/时间);逐窗写 access_log `export`。文件经 service role 从私有 bucket 读取后在本端点打包;单窗文件读取失败 500 `WMS_SERVER_001` 人话可重试 **【2026-11-06 本地调取改造注记(REQ-20261106-35/D97 §14)】**:行为变更——证据包改 **Hub 侧组包**(zip=录像+快照图+timeline.json 由 Hub 生成、经下载通道回传),前置条件从「全部窗口 fetch done」改为「**Hub 在线**」;**随批三生效**(中继+组包真链点亮),**批一阶段本端点先诚实不可用**:回人话不可用原因(宿主 Hub 离线/功能随批三上线)、不再出现「先调取到云端」类文案与 409 旧口径;access_log `export` 留痕口径不变

GET/api/wms/pack-vision/stations/status

打包台录像状态逐台位面(REQ-20261103-11 / D97 §4),打包台页状态区与将来全局设备指示共用同一事实源。AI/agent 只读工具登记见 agent 工具注册表 `get_wms_pack_vision_stations_status`。

GET/api/wms/pack-vision/sessions

打包会话·活跃会话清单(2026-11-06 批一 B1-C,REQ-20261106-35/D97 §14.7):回本组织活跃/暂停会话摘要(session_id/shipment_id/shipment_no/station_id/station_label/operator_user_id/status/started_at/last_activity_at/idle_minutes/hung_minutes/progress/takeover_direct_available)。**2026-11-07 B1-E 加法**:会话操作员=当前登录用户时逐条查待确认接管请求(组织 idle TTL 口径),命中加法带 `pending_takeover{to_station_id, to_station_label, requester_user_id, requested_at}`(to_station_label 按 to_station_id 查本组织台位表拼 name (code)、查不到为 null,打包台待确认弹窗点名申请台位、null 时回退中性表述),其余会话不带、单条查询失败不拖垮清单。鉴权:withWms 宽松默认+organization_id 隔离

GET/api/wms/pack-vision/metrics/cycle-time

打包效率节拍聚合(2026-11-03 v2 效率版,REQ-20261103-24 / D97 §10)。效率页(WMS「打包效率」)节拍对比/分段耗时/停顿与空窗分布的数据源。口径单一事实源=存档设计稿 §6.4 计时口径附注,实现落点 `apps/wms/app/api/wms/pack-vision/metrics.ts`(CALIBER 常量+纯函数 buildCycleTimeResult),route 只做薄转发。本端点不新增 AI/agent 工具登记(聚合统计面给 UI 用)。

GET/api/wms/pack-vision/metrics/long-orders

异常长单清单(2026-11-03 v2 效率版,REQ-20261103-24 / D97 §10)。效率页异常长单区的数据源;每行「看录像」深链由门面拼 `/wms/pack-vision?window_id&shipment_id&focus_s=focus.offset_s` 打开回放定位,本端点只出清单与 focus。口径与阈值/focus 计算单一事实源 `apps/wms/app/api/wms/pack-vision/metrics.ts`(computeLongOrderThreshold/computeFocus)。本端点不新增 AI/agent 工具登记(聚合统计面给 UI 用)。

GET/api/wms/pack-vision/check-plans

AI 检查计划列表(2026-11-03 批三-B v3 模拟批,REQ-20261103-41 / D97 §11)。打包台 PackVisionPanel 的数据面:Panel 10s 轮询本站计划,经门面呈现模拟横幅(本站有 ai 计划或 simulation 事件才呈现)与最新未核对 warn 提醒条。计划由云端绑定引擎在触发点写入(开窗 sample/anomaly、扫码放件 item_scanned 的 count+match、面单生成 before_seal 的 count/match/seal/label 四查;同窗同触发点同种类已有 pending/claimed/done/acked 时不重复建),Hub 按台位领取执行、结论按 window_id 写 pack_video_events(event_type='ai')。口径单一事实源 `apps/wms/app/api/wms/pack-vision/check-plans.ts`(listCheckPlansForStation),route 只做薄转发。本端点不新增 AI/agent 工具登记(台位门面内部轮询面,非 agent 消费面;既有两只读工具不变)。

POST/api/wms/pack-vision/check-plans/{id}/ack

AI 检查「已核对」回执(2026-11-03 批三-B v3 模拟批,REQ-20261103-41 / D97 §11)。操作员在打包台对 AI 检查提醒点「已核对,继续」的落点:守存档稿 §7.2 只提示不拦截——ack 只把检查计划置 acked 并追加一条 ai 留痕事件(回流作误报样本),**不改任何订单/打包状态**。逻辑单一事实源 `apps/wms/app/api/wms/pack-vision/check-plans.ts`(ackCheckPlan),route 只做薄转发。本端点不新增 AI/agent 工具登记(写操作;沿 v1 口径——调取/导出等写操作不经 agent 工具、走页面按钮)。

GET/api/wms/pack-vision/overview

索引服务总览(2026-11-06 批 1b,REQ-20261106-42 / 设计 v2.3 §2.4 `getOverview`):台位/Hub/摄像头/录像机状态聚合+未绑定与异常计数。summary 判定链与空窗探查逐字对齐 stations/status(窄修 P2-5:含 has_gaps 与 gap_windows_24h/current_window 字段);计数面过滤合并源段(merged_into_id 非空,窄修 P2-8)、异常按片段去重(窄修 P3-6)。逻辑单点 `apps/wms/app/api/wms/pack-vision/index-service.ts`(本批新端点共同单点,下略),route 薄转发。本组端点(overview 起至 connections)均**不新增 AI/agent 工具登记**——门面经服务契约消费的底座服务面,租户只取 ctx.orgId。

GET/api/wms/pack-vision/segments

片段列表(§2.4 `listSegments`):过滤 station_id/tracking_id/external_order_ref/status/kind/from/to(opened_at 半开区间)+游标分页(limit 封顶 100、回 next_cursor),查 pack_video_windows;merged_into_id 非空的合并源段不入列表(窄修 P2-8)。

GET/api/wms/pack-vision/segments/{id}

片段详情(§2.4 `getSegment`):按 id 直取,合并源段也可查(窄修 P2-8)。**Errors**:404 `WMS_NOT_FOUND_001`(不存在或不属于当前组织)。

POST/api/wms/pack-vision/segments/{id}/bind

落绑/改绑(§2.4 `bindSegment`):body `{tracking_id?, external_order_ref?, bind_source?, reason?(改绑必填), idempotency_key?}`(幂等键可走 Idempotency-Key 头,本组写端点同)。改绑(目标已 bound)reason 必填(窄修 P2-7);冻结片段一律拒绝;写审计 bind/rebind。**Errors**:400 `WMS_VALID_001`、404、409 `WMS_STATE_001`(冻结/状态不允许,人话)。

POST/api/wms/pack-vision/segments/{id}/unbind

解绑(§2.4 `unbindSegment`):reason 必填,仅 bound 可解,冻结拒绝;写审计 unbind。

POST/api/wms/pack-vision/segments/{id}/split

索引层切分(§2.4 `splitSegment`、§5.5):body `{split_at*, reason?, idempotency_key?}`;建两子段行、父段置 split+split_pending,Hub 执行回执不在本批;冻结拒绝;写审计 split。

POST/api/wms/pack-vision/segments/{id}/merge

索引层合并(§2.4 `mergeSegments`、§5.5):body `{other_segment_id*, reason?, idempotency_key?}`;同台位两段合成新行、源段置 merged_into_id+merge_pending(源段自此退出列表/计数/建议活跃面,窄修 P2-8);源段已合并过回既有合并段(重入守卫,窄修 P2-2);任一冻结即拒绝;写审计 merge。

POST/api/wms/pack-vision/segments/{id}/freeze

证据冻结(§2.4 `freezeSegment`、§5.6):置 flags.frozen,幂等;写审计 freeze。

POST/api/wms/pack-vision/segments/{id}/unfreeze

解冻(§2.4 `unfreezeSegment`、§5.6):仅负责人级 owner/admin(窄修 P2-1:服务层按登录用户现查组织成员关系解出角色,请求体自报 actor_role 不采信),reason 必填;写审计 unfreeze。**Errors**:403 `WMS_PERM_002`(非负责人级,人话)。上线闸同表格组 unfreeze 行。

POST/api/wms/pack-vision/segments/{id}/retrieval

建调取任务(§2.4 `createRetrievalJob`):body `{kind?, range_start?, range_end?, expires_at?, idempotency_key?}`;同 window 同 kind 已有 queued/fetching 回既有任务;写审计 retrieval_create。

GET/api/wms/pack-vision/unbound

未绑定队列(§2.4 `listUnbound`、§5.4):query station_id/flag/limit/cursor,游标分页;合并源段不入队列(窄修 P2-8)。

GET/api/wms/pack-vision/unbound/{id}/suggestions

建议匹配(§2.4 `getBindingSuggestions`、§5.4):最多 3 候选+reason_code(queue_order/label_time_anchor/pairing_gap),只建议不落绑;冻结片段可查(只读,窄修 P3-1);候选缺口判定过滤合并源段(窄修 P2-8)。

GET/api/wms/pack-vision/retrieval/{id}

调取任务进度(§2.4 `getRetrievalJob`,映射 pack_video_fetch_requests)。status 枚举=`queued/fetching/ready/done/failed/expired`(契约正本 pack-contract.ts FETCH_STATUSES;`ready`=独立模式 LAN 本地副本已就绪、未上云,与 `done`=已上云带 cloud_path 严格区分,批 2 窄修经 migration 893 扩值);ready 行带 LAN 交付列 `lan_access_token/lan_token_issued_at`(token 一次性取用、随 expires_at 失效、过期不得下发)。**Errors**:404 `WMS_NOT_FOUND_001`。

GET/api/wms/pack-vision/pairings

配对列表(§2.4 `listPairings`):query tracking/order_no/status/limit/cursor。

POST/api/wms/pack-vision/pairings/manual

手工建配对(§2.4 `upsertManualPairing`、§5.2):source='manual'、唯一键 (organization_id, tracking) 幂等 upsert,写 pairing_events(confirmed)+审计 pairing_upsert;同幂等键先按审计回查、命中即回既有配对(窄修 P3-4,同键异内容不再静默改挂);与既有非人工配对冲突 409 交人工裁决。

POST/api/wms/pack-vision/hubs/pair

Hub 配对(§2.4 `pairHub`、§6.2):body `{pairing_code*, hub_id?, station_id?, idempotency_key?}`;码哈希比对 device_hubs.pairing_code_hash、配对成功即清码;有效期(pairing_code_issued_at 超 pack_config ttl、缺省 10 分钟拒绝,窄修 P2-4)+失败限流(hub_pair_failed 审计计数、窗口内达上限拒绝,窄修 P2-4);同键重投按审计回查解密 token_enc 回凭证明文(token_recoverable 标记可恢复性,窄修 P2-3),响应 `{hub, device_token, token_recoverable, duplicate}`、库里只存哈希;不做任何数量上限校验;写审计 hub_pair。

POST/api/wms/pack-vision/hubs/{id}/unbind

解绑 Hub(§2.4 `unbindHub`):吊销设备凭证、清配对状态,历史索引不删;写审计 hub_unbind。

PUT/api/wms/pack-vision/stations/{id}/config

台位配置(§2.4 `setStationConfig`、§5.1):body `{scan_timing_mode?, timezone?, idempotency_key?}`(至少一项),落 wms_packing_stations,下个片段起生效;写审计 timing_mode_change/station_config。

GET/api/wms/pack-vision/audit

审计列表(§2.4 `listAudit`、§7.5):query target_type/target_id/action/limit/cursor,只追加只读(留痕面不做合并源段过滤,窄修 P2-8 口径)。

GET/api/wms/pack-vision/connections

平台连接状态(§2.4 `getConnectionStatus`):query platform?;只回状态面、不回凭据。startConnection/handleConnectionCallback/submitLabelPdf/confirmPairingCandidate 不在本批(批 4 B-6)。

POST/api/wms/pack-vision/connections/start

打包录像·发起平台连接(批 4A / §2.4 `startConnection`):body `{platform*(shopify/shipstation), shop_domain?, redirect_uri?, idempotency_key?}`。同平台同域名已有 pending/active 连接直接复用不重复建(P3-5 表达式唯一索引兜底,migration 898);Shopify 回授权 URL(平台应用 client id 由服务端环境配置,未配置回 `authorizationUrl=null, authConfigured=false` 不假装可授权;redirect_uri 由调用方传、底座不内置域名),ShipStation 为 API Key 口径无授权 URL。凭据永不经本端点;写审计 connection_start

POST/api/wms/pack-vision/connections/callback

打包录像·连接凭据落库(批 4A / §2.4 `handleConnectionCallback`):body `{connection_id*, credential*(字符串或对象), shop_domain?, scopes?, idempotency_key?}`。凭据只经既有加密通道(shared_encrypt_secret)落 `credential_enc`(898 新列),审计只记 `credential_set` 布尔、**凭据明文不落库不落日志不回显**;连接转 active。Shopify 的 OAuth code 换 token 由调用方服务端完成、本端点只收最终凭据;ShipStation 凭据={apiKey, apiSecret} 整体加密

DELETE/api/wms/pack-vision/connections/{id}

打包录像·断开平台连接(批 4A / `disconnectConnection`):body `{reason?, idempotency_key?}`;连接转 disconnected 并清凭据密文(防断开后残留可用凭据);历史配对不删;写审计 connection_update

POST/api/wms/pack-vision/connections/{id}/sync

打包录像·拉取平台配对(批 4A / `syncConnectionPairings`):body `{since?, idempotency_key?}`。服务端解密凭据(只在内存)经连接器注册表拉订单↔tracking(Shopify REST orders / ShipStation shipments)逐条落配对事实面(source=api)并尝试自动落绑;连接须 active 且有凭据,否则 409 人话;拉取失败连接转 error 并 500 人话(错误只带平台+HTTP 状态、不回显响应体与凭据);本端点不写审计(批 4 窄修订正:逐条配对经 pairing_events matched 留痕,连接状态变更经 last_webhook_at/状态行呈现)

POST/api/wms/pack-vision/pairings/pdf

打包录像·面单 PDF 摄入(批 4A / §2.4 `submitLabelPdf`):body `{file_name*, file_base64*(≤10MB), idempotency_key?}`。收件箱幂等键=租户作用域键 `org:文件 SHA-256`(批 4 窄修 P2-1:收件箱唯一键全局、无 org 列,键自带租户维度——跨租户同文件不误判 duplicate、同租户重传回 duplicate 不重复建候选);解析=PDF 文本层抽取(按内容流分段)+承运商号式识别(选型理由见设计稿 §14.8),逐 tracking 生成待确认候选(pack_pairing_candidates,source=pdf),**候选一律人工确认才落事实面**(含高置信);订单号提示按面单段归属各候选(detail.order_no_hint+hint_scope,多面单不共享、无法归属不给,批 4 窄修 P2-2);抽不到 tracking 不丢弃——落 parse_failed 候选(tracking 空)进人工队列补录;文件字节本体不落库

GET/api/wms/pack-vision/pairings/candidates

打包录像·待配对候选队列(批 4A / `listPairingCandidates`):query `status?`(默认 pending)、`limit`/`cursor`;行=pack_pairing_candidates(tracking 可空=待人工补录、confidence、detail 含订单号提示/文件名/识别式说明)

POST/api/wms/pack-vision/pairings/candidates/{id}/confirm

打包录像·确认候选(批 4A / §2.4 `confirmPairingCandidate`):body `{tracking?, order_no?, idempotency_key?}`——人工录入兜底字段:tracking/order_no 可在此补齐(订单号回退链:人工录入 > 候选已存 > PDF 订单号提示);确认经唯一写者落配对事实面(source 沿候选来源)并尝试自动落绑;已确认再确认幂等回既有配对;写审计 candidate_confirm

POST/api/wms/pack-vision/pairings/candidates/{id}/reject

打包录像·否决候选(批 4A / `rejectPairingCandidate`):body `{reason?, idempotency_key?}`;候选转 rejected 退出待确认队列(行保留留痕,pending 部分唯一索引自动释放该 tracking);写审计 candidate_reject

POST/api/wms/pack-vision/inbox/process-scans

打包录像·定段消费(批 4A / `processPendingScanEvents`,双时序定段 §14.8):body `{limit?(默认 20、封顶 100,clampLimit 口径,批 4 窄修订正)}`。消费 pack_event_inbox 未处理 hub_event——扫码事件按台位 scan_timing_mode 定段(封箱扫:扫码关当前段、码落该段、随即按 preroll 开新段;开单扫:扫码关上一段、以码开新段),录像机 segment_opened/closed 事件按 hub_segment_key 定位同段行;租户由 Hub 注册行反解;**按租户公平消费**(批 4 窄修 P2-4+二轮 P2-4R):先取本 org 的 Hub 集合、取数按 payload hub_local_id 服务端过滤,他组织行根本不进取数面(回执 skippedForeign 恒 0、仅保留字段形状),limit 只计本 org 消费行,单租户积压不饿死他租户。幂等三层(processed 标记+scan_segment 审计回查——只覆盖 hub.scan+hub_segment_key 定位与状态守卫——覆盖生命周期事件);异常段(缺起点等)落未绑定面+flags 标因不静默吞,逐事件 outcome 回执。触发方=门面/定时面,底座不内置调度

POST/api/wms/pack-vision/webhooks/{platform}

打包录像·平台 webhook 公开入口(批 4B / 设计 §7.7 底座·webhook):**无用户会话、验签即凭证域**——验签在任何落库之前、失败 401/400 明确拒绝不落行。shopify=`X-Shopify-Hmac-Sha256` 对原始体 HMAC-SHA256(secret 环境配置 `SHOPIFY_CLIENT_SECRET`,未配置回 503 `webhook_not_configured` 不假装能验),租户由 `X-Shopify-Shop-Domain` 反解连接行、事件 id 取 `X-Shopify-Webhook-Id`;shipstation=平台官方无签名机制(2026-11-06 按官方 webhook 文档核实),按连接 token 验(query `connection_id`+`token`=HMAC-SHA256(`SHIPSTATION_WEBHOOK_SECRET`, 'shipstation:<connection_id>'),门面生成订阅 URL、两侧同算法),事件 id 以原始体 SHA-256 充当、收件箱幂等键加连接维度。验签后交批 4A `handlePlatformWebhook`(收件箱幂等→连接器解析→配对落面);**shipstation 分支只记通知不从体写配对**(批 4 窄修 P2-5:官方通知只含 resource_url、自造 shipments 体一律不落配对,真实配对以 sync 拉取为准);本组端点为门面经服务契约消费的底座面、不经 agent 工具(与批 1b/4A 各行同口径)

面单模板/api/wms/label-templatesGETPOSTPATCHDELETE12 个接口

GET/api/wms/label-templates

查询标签模板列表(六类合并表,附零售商信息),默认只返回启用的。REQ-20261103-34:内置模板改「跟随」呈现——is_builtin 且带 source 血统的行,name/version/size/label_kind/media/content 一律解析为平台同族当前 published 版(同族 published+启用+非紧急停用取最高版;最高版被紧急停用则整族无当前版、不回落旧版,行上带 platform_emergency);平台有当前版而本组织无任何锚点的族合成虚拟行(id=平台行 id、is_builtin=true);全族退役时回落本地副本并以 platform_status 标注。每行另附 retailer_logo_url(retailer 有真实 logo 资产时为 `/api/wms/retailer-logos/{code}`,否则 null)。分页口径注记:同族多副本在呈现层收敛为一个代表行,收敛按页执行——逐页消费时 meta.total 为页口径(各页可能略有出入),虚拟行只在末页返回;服务端 page_size 上限 100,需全量时请循环分页拉到末页(模板中心页即此口径)

POST/api/wms/label-templates

新建标签模板(模板名同组织唯一、格式 retailer-size-kind-Vn;UCC 模板必须指定 label_kind)。D68 起:内容引用当前介质出不来的变量(如 ZPL 标签版引用品牌图 [[BRAND_LOGO]])时不拦保存,成功响应 meta.warnings 带大白话提示。REQ-20261103-34:clone_source_id 可为平台行 id(虚拟内置)或本组织内置行,两路都先解析平台同族当前版为克隆内容、产物脱钩(is_builtin=false);clone_from_version 点名某历史版本时取该版本,点名不存在直接 404、不静默回落当前版。

GET/api/wms/label-templates/{id}

标签模板详情:含 ZPL 源码和关联零售商信息。

PATCH/api/wms/label-templates/{id}

编辑标签模板:ZPL 内容变化时版本号自动+1。REQ-20261028-07 起每次保存成功后写一行版本快照(change_kind 按归属/启用/ZPL 变化判定),快照写入失败如实报错(主行已保存)。D68 起:内容变更时同 POST 口径给介质适配提示(meta.warnings,不拦保存)。

GET/api/wms/label-templates/{id}/versions

模板版本历史(REQ-20261028-07,migration 637 快照表):不带参数返回版本列表(元数据,版本号降序,不含 ZPL 正文);?version=N 返回单个版本快照(含 zpl_content),供详情页查看历史版本与克隆取数。权限点 wms.label_templates.view。快照的 changed_by 为用户 ID(内部审计用,页面不展示)。

POST/api/wms/label-templates/render

渲染标签:用给定值替换模板占位符,返回替换后的 ZPL(列出未解析的占位符)。REQ-20261103-34:内置模板按平台同族当前 published 版渲染;同族当前版被紧急停用(整族无当前版)时返回 409 `WMS_TEMPLATE_001`(含 emergency_reason)拦下打印,不回落旧版副本。

POST/api/wms/label-templates/extract-jobs

D66 增补 §21(REQ-20261029-43):AI 样本生成——multipart 上传样本(≤10MB)建抽取任务;ZPL 确定性解析/PDF 文本层优先,图片与无文本层 PDF 走视觉通道(2026-10-30 接通,经平台内部端点调视觉大模型,失败如实 failed 给降级路);视觉调用 token 按组织计 AI 用量、本次用量随任务提案回显;组织月度软上限 20 次(常量 TEMPLATE_EXTRACT_MONTHLY_SOFT_LIMIT,防跑飞安全闸、非计费闸)

GET/api/wms/label-templates/extract-jobs

同上:?result_template_id= 列某模板挂着的保留样本(详情页 §21.3 挂载)

GET/api/wms/label-templates/extract-jobs/{id}

抽取任务轮询口径:状态+提案 JSON+样本临时下载链接(sample_url)

GET/api/wms/label-templates/extract-jobs/{id}/rounds

**新增(REQ-20261102-52 批三,D93 §3.8)**:轮次链读取——版本链+当前轮内容+待确认问题清单+AI 轮次用量(组织隔离:任务须属本组织且 scope=tenant)

POST/api/wms/label-templates/extract-jobs/{id}/rounds

**新增(同上)**:body.action 分发——create(以确认步内容建第 1 轮并在此按 job 幂等扣一口价:Label 1000 / Packing List 2000 Credit 直落 usage_events、计量点 template_ai_extract qty=0 防双计,见 migration 786;或 manual_edit 人工轮)/feedback_structured/feedback_ai(经 core 内部 template-revise;硬顶 10)/rollback/preview(三模式;真单走生产 values 构建器 buildPackingListValues、organization+retailer 双条件强制、本组织无该 retailer 单即 422 不凑数、渲染不落盘只留不含字段值的元数据)/candidates/save(过 assertSaveable 准入门:error 轮拒存、越界逐项确认、有真单未预览拒存;落 wms_label_templates draft 未启用+v1 快照 changeKind=ai_generate、任务置 saved)/abandon。同组织串行护栏同步加于 POST `/api/wms/label-templates/extract-jobs`(有进行中任务时 WMS_UNPROC_001)

DELETE/api/wms/label-templates/extract-jobs/{id}/sample

手动删除保留的样本原件(文档中心原件+清 storage_key 指针)

面单批次/api/wms/label-batchesGETPOST4 个接口

POST/api/wms/label-batches

建 Label 先行批次(D64/REQ-20261029-28):body { shipment_ids*, batch_type*(single_unit/single_carton), filter_snapshot? };服务端单点跑资格判定+RS 定服务+锁库存,返回 { batch, items, okIds, excluded:[{shipment_id, reason(设计稿 §7 原因码)}], reused };「零单合格」或「所选单全已在其他批次」为业务结局(非错误):仍回 200 且 batch=null、items/okIds 为空、excluded 为完整逐单报告(REQ-20261030-03);同集合已全部在同一在途批次时回既有批次(reused=true,不重复建批);超单批上限(租户设置 label_batch_max_items,默认 500)回 WMS_VALID_001+details.reason='label_batch_too_large'。权限 wms.outbound.create+组织隔离,客户用户逐单数据范围校验

GET/api/wms/label-batches

批次分页列表(?page&page_size&status,服务端 .range() 分页+count,禁全量);?open=1[&date=YYYY-MM-DD] 时回当日未关单批次(status ∈ purchased/printing/printed/fulfilling)——EOD 告警与列表页「未关单」过滤共用此派生口径。权限 wms.outbound.view

GET/api/wms/label-batches/{id}

批次详情:批次行+逐单行(seq/状态/来源/承运商服务/tracking/剔除原因)+freight { estimated_total(preview/确认冻结值,未购买为 null), actual_total(Σ carrier_api 行确认价;附件/渠道行不产运费不计入,无已购 carrier_api 行为 null) }。权限 wms.outbound.view+批次仓库数据范围校验

POST/api/wms/label-batches/{id}/{action}

批次动作查表分发(未知 action 回 WMS_NOT_FOUND_001+details.allowed 列全集):preview(只读询价汇总 {total, unpriced_count, rows},只询价不购买)/purchase(**必须带 confirmed_total 且与 preview 总额一致**,缺失或对不上均 WMS_VALID_001 且不买任何一单;逐单走来源三级解析〔附件>渠道>承运商 API〕取 label,失败单隔离不堵整批)/print(进门先复查剔除并入响应 recheck;body {seqs?|from_seq?} 装配同序打印任务〔label+pick list+渠道 packing slip 成对〕并记出纸序号)/reprint({seq} 按号重印原单,永不重新购买)/attach({shipment_id} 拣贴完成确认 printed→attached)/eject({shipment_id, reason?} 逐单剔除:先按来源作废 label+释放本批库存锁,原因记 label_ref 不写 exclude_reason 列)/close(关单前复查为硬关口+批量 fulfill,返回逐单结果 closed/failed/ejected;部分关单为合法终局 partially_closed)/handover(按 carrier/service 分组交接单数据 {groups:[{carrier, service, tracking_numbers, count}], total})/cancel(取消批次:已购未用 label 按来源自动作废+释放本批锁,作废失败逐单列明不静默)。读动作 wms.outbound.view、写动作 wms.outbound.edit

打印任务/api/wms/print-jobsGETPOSTPATCH6 个接口

GET/api/wms/print-jobs

打印中心 → 打印队列列表(Andy 2026-10-13)。

POST/api/wms/print-jobs

云打印任务下发:把打印任务写入 print_jobs(queued),仓库电脑上的 Device Hub 订阅/轮询拉走打印后回写 done/failed。两种任务:job_kind=label(默认,ZPL 标签)与 job_kind=document(PDF 单据,2026-10-23 打印设置完善新增)。指定 device_id 时校验设备 printer_kind 与 job_kind 一致(带 paper 尺寸时另校验装纸 ≥ 任务尺寸);不传时走 D33 默认链(用户默认→仓库默认→组织默认,逐级校 Hub 在线+纸型适配,降级明示;无默认回 422 带 selection_required 候选)。

GET/api/wms/print-jobs/{id}

查单个云打印任务状态(手机端轮询用)。

PATCH/api/wms/print-jobs/{id}

打印任务操作:cancel 取消排队中任务(仅 queued),retry 重试失败任务(仅 failed);状态机原子更新,状态已变则冲突。

POST/api/wms/print-jobs/batch-labels

批量面单入队(Orderball 打印设计 D11 §8.2,REQ-20261024-54):给一批订单在底座侧逐单取面单载荷、生成面单 ZPL(复用 WMS 面单生成器 `shippingLabelZpl`),每单一台标签机一行 queued 任务写入 print_jobs,等 Device Hub 领取打印。载荷为演示面单口径(本地追踪号)时 ZPL 注明 DEMO。逐单回结果:订单不存在、还没出面单(未发货/无追踪号)只影响该单;整批皆败回 422。同一(订单+设备)1 分钟内已有 queued/printing 任务时回既有任务行并标 deduped,不重复建行。device_id 必传且显式指定即信任(不查 Hub 在线状态,离线先入队、Hub 上线后领取)。

POST/api/wms/print-jobs/{id}/reprint

历史补打(Orderball 打印设计 D11 §8.2,REQ-20261024-54):把一条已打完(done)的任务原样复制成一条新 queued 任务再打一次(新行自己的 id/created_at,审计上补打次数=按原行引用回溯的复制行数)。failed 任务不走这里(用 PATCH /api/wms/print-jobs/{id} 的 action=retry 原行复活)。原行内容列已被保留期清理(90 天,cron 任务 print-jobs-content-cleanup)时回 410 PRINT_CONTENT_EXPIRED 并给人话出路(回订单页重新打印)。

Accounts/api/labelflow/accountsGETPOSTPATCHDELETE4 个接口

GET/api/labelflow/accounts

租户承运商账号列表:查本租户接了哪些快递账号

POST/api/labelflow/accounts

新建快递账号:把一家快递公司的账号接进来,可同时关联共享承运商账号

DELETE/api/labelflow/accounts/{id}

删除快递账号

PATCH/api/labelflow/accounts/{id}

更新快递账号:改别名、启停用、备注或关联的共享承运商账号

Deposits/api/labelflow/depositsGETPOSTDELETE4 个接口

GET/api/labelflow/deposits

存款流水:查商户往钱包里充了哪些钱

POST/api/labelflow/deposits

手工存款:给商户钱包充钱并记一笔流水

POST/api/labelflow/deposits/evidence

上传一个存款凭证文件(multipart,图片/PDF/文档,≤10MB),存私有桶 labelflow-evidence,回文件引用供存款提交时随 evidence_files 带回

DELETE/api/labelflow/deposits/evidence

删除一个本组织前缀的凭证文件(表单中删掉未保存的上传用);已被流水 evidence_files 引用的已落账凭证回 409 EVIDENCE_IN_USE 拦截,不许在此删除

设置/api/labelflow/settingsGETPUT2 个接口

GET/api/labelflow/settings

LabelFlow 租户设置(Portal 呈现部分,REQ-20261025-14):读 lf_settings 的 portal_recharge_guide(对客线下充值指引)+ wallet_low_balance_threshold(低余额提醒阈值 USD)

PUT/api/labelflow/settings

同上保存(upsert 一组织一行):guide ≤2000 字、threshold ≥0 或 null(null=Portal 缺省 $25);Deposits 页设置卡调用

发票/api/labelflow/invoicesGETPOST4 个接口

GET/api/labelflow/invoices

承运商账单列表:每张账单附对账汇总(总行数/差异行数)

POST/api/labelflow/invoices

导入承运商账单:把账单明细行存进来准备对账

POST/api/labelflow/invoices/extract

发票 AI 导入第一步:上传账单文件产「草稿」(不入账)——原件先存私有桶留存,确定性解析优先(CSV/Excel 表格列名映射、PDF 文本层行式,不耗 Credit),命中不了才走平台抽取核(LLM,purpose=labelflow_invoice_extract、计 Credit 算租户);用户在核对面确认后才走 POST /api/labelflow/invoices 入账

GET/api/labelflow/invoices/{id}

账单详情:某张承运商账单及其对账结果行

Labels/api/labelflow/labelsGET1 个接口

GET/api/labelflow/labels

面单记录列表:查打过哪些面单,附成本/收费/利润

Markups/api/labelflow/markupsGETPOST2 个接口

GET/api/labelflow/markups

承运商级加价配置列表:查每个承运商的基础加价率

POST/api/labelflow/markups

新增或更新承运商级加价配置

Merchant Rates/api/labelflow/merchant-ratesGETPOST2 个接口

GET/api/labelflow/merchant-rates

商户级费率覆盖列表:查某个商户对某承运商的单独加价

POST/api/labelflow/merchant-rates

新增或更新商户级费率覆盖

Merchants/api/labelflow/merchantsGETPOST3 个接口

GET/api/labelflow/merchants

商户列表:每个商户附钱包余额、面单数和不良行为数

GET/api/labelflow/merchants/{id}

商户详情:基本信息、钱包、最近存款和面单记录

POST/api/labelflow/merchants/{id}/unban

解封商户钱包:把停用的钱包恢复成 active

Print Label/api/labelflow/print-labelPOST1 个接口

POST/api/labelflow/print-label

打单全链路:校验钱包余额后直接打面单并扣费

Quote/api/labelflow/quotePOST1 个接口

POST/api/labelflow/quote

打单前报价:按商户/承运商两档费率算出应收金额

Reconcile/api/labelflow/reconcilePOST1 个接口

POST/api/labelflow/reconcile

跑对账:拿承运商账单和我们的收费逐单比对,差异超阈自动扣款

出库单/api/labelflow/shipmentsGETPOST7 个接口

GET/api/labelflow/shipments

运单列表:查手工建单和 CSV 导入的运单

POST/api/labelflow/shipments

手工建运单:填收发件信息和包裹建一条 draft 运单

GET/api/labelflow/shipments/{id}

运单详情:附已打印面单的运单号

POST/api/labelflow/shipments/{id}/print

选中比价结果打单:先验余额、先扣款、再打印

POST/api/labelflow/shipments/{id}/quote

运单比价:给一条运单算出可选的承运商报价列表(actual 模式未指定承运商时跨承运商比价,REQ-20261108-05/RS-1;指定承运商走单家最优匹配,口径不变)

POST/api/labelflow/shipments/import

CSV 预览校验:只校验不写库,返回合法行和错误行

POST/api/labelflow/shipments/import-confirm

CSV 导入确认:把预览校验通过的行批量建成 draft 运单

Rate Estimate/api/labelflow/rate-estimatePOST1 个接口

POST/api/labelflow/rate-estimate

运费试算(RS-2,REQ-20261108-05):只算价不落单——按 Merchant、目的地与包裹走与运单 quote 相同的询价口径返回比价选项;不建运单、不写库、不扣款。入口页面 LabelFlow → 运费试算(/labelflow/rate-estimate)

Violations/api/labelflow/violationsGET1 个接口

GET/api/labelflow/violations

商户不良行为列表:查哪些商户被记过(如重量不符)

Wallet/api/labelflow/walletGET1 个接口

GET/api/labelflow/wallet

查商户钱包:余额加最近 20 笔流水

汇集24 个接口

汇集/api/wms/consolidationGETPOSTPATCH13 个接口

POST/api/wms/consolidation/scan

汇集区入口扫码:扫车码或扫 tote,系统校验 batch 一致性并返回该 tote 应该去的格子(已有格子就复用,没有就分配一个空格子)。扫码枪直接调。扫车定位批次口径(2026-11-03 缺陷修复,REQ-20261103-33):由车上各 tote 最新 assignment 的候选批次中先取 open/consolidating、再取 assignment 最新者;车上残留的旧批次 tote(指向已关闭批次)不影响定位,全部候选都已关闭时才回 BATCH_NOT_OPEN。

POST/api/wms/consolidation/slot-confirm

格口确认事件(2026-11-03 通道无关定版,Andy 亲裁,与 D91 播种墙同源):工人把 tote 放到格子后确认放对(防放错格)。本端点处理的是确认事件本身,不绑定扫码通道——状态推进只认事件;现行通道是扫格子码,播种墙拍灯(D91)与语音确认将来同语义调用本端点。到齐时返回 ready_to_merge=true,提示"可以合箱",并给出系统预估的出货箱数。2026-11-03 放格定版:确认成功后 tote 当场释放回池(status→idle,与 merge 回流同口径、merge 侧幂等空转);到齐通知 wms.consol.ready 由本端点在最后一只入格时发(整车签到不再记收)。

POST/api/wms/consolidation/slot-overflow

满格溢出(2026-11-03 新增,Andy 定版四点优化④):物理格口放不下时,操作员标记溢出,系统给同一订单再分一个关联格口;该单此后两格并行有效(scan/slot-confirm 按该单未释放格口集校验),看板以 slot_codes[] 绑定呈现。再无空格口回 NO_EMPTY_SLOT。

GET/api/wms/consolidation/board

和单看板:按 batch 看每单的格子、应到/实到 tote、各 zone 任务状态、是否可合箱,颜色区分 waiting/partial/ready/merged。主管盯进度的主屏。

GET/api/wms/consolidation/overview

全仓批次总看板 + 批次列表(2026-10-20 点 6/8 新增,本阶段唯一新端点):给 Consolidation 看板落地页用。默认 overview 模式返回当前仓库全部活跃批次(open/consolidating)的跨批次总览;mode=list 返回该仓全部状态的近期批次列表。仓库口径 = 参数 warehouse_id(页面取顶部已选仓库);批次的仓库归属经出库单推导(批次表无 warehouse_id 列)。

GET/api/wms/consolidation/slot-pool

汇集区格口池维护(2026-10-20 点 9 新增):格口池 = 本仓汇集区实际存在的物理格全集(主数据表 wms_consolidation_slot_pool,migration 494)。维护页据此管理格口;建池后 checkin / slot-confirm 只认池内 active 格(校验分档,没建池的仓零影响),总看板全景墙按池全集展示(含空闲格)。仓库口径 = 参数 warehouse_id(页面取顶部已选仓库),服务端做仓库数据范围校验。

POST/api/wms/consolidation/slot-pool

格口池新增:action=create 逐个新增一个格口;action=generate 按前缀 + 起止号批量生成(已存在的自动跳过,重复提交不产生重复格)。

PATCH/api/wms/consolidation/slot-pool

格口池维护修改:改号 / 改排序 / 改备注 / 启停(停用不删,停用后交接扫码不再接受该格,全景墙显示为停用)。

GET/api/wms/consolidation/parking-spots

停车位登记册(REQ-20261103-40):列本仓汇集区登记册全集(每行带未关闭签到推导的 occupied_by)+ 汇集区列表;labels=1 附启用车位 QR 标签 ZPL(code= 只出单个)

POST/api/wms/consolidation/parking-spots

停车位登记册:新建车位——编号服务端按汇集区顺号生成(P-01 起),请求 code 不采信(不许自编)

PATCH/api/wms/consolidation/parking-spots

停车位登记册:改备注/启停(id 放 body;编号不可改,停用不删)

POST/api/wms/consolidation/merge

合单确认(2026-11-03 Andy 定版改版「合单去扫箱」,REQ-20261103-34):不再扫出货箱。合单前系统硬校验三道——批次 open/consolidating、"实到==应到"、"各 tote 确认数量加总==订单需求",不对就拒绝。成功后和单行转 merged、释放格子、tote 回流(与改版前一致);不再写 wms_consolidation_merges、不再回写 actual_cartons(carton 记录下游零消费,实证见设计稿 zone-pick-design §6.8/§9.1)。

POST/api/wms/consolidation/pickup

扫格口取货(2026-11-05 新增,REQ-20261105-06,汇集装箱 B 模式):body `{slot_codes[], transfer_tote_code}`——逐格扫码确认收齐(缺格回 PICKUP_SLOTS_INCOMPLETE 点名缺格)+转运 tote 绑定,原子推进 ready→picked_up、释放全部格口、计费事件同 merge 口径在取货点触发;A 模式单回 MODE_PACK_AT_SLOT、未定格存量单回 MODE_NOT_SET、未到齐复用 NOT_READY

拣货车/api/wms/tote-cartsGETPOSTPATCHDELETE6 个接口

GET/api/wms/tote-carts

查询拣货推车列表(附每车箱格总数/空闲数/使用中数和当前停靠位置编码)

POST/api/wms/tote-carts

新建拣货推车(按箱格数自动生成箱格,license_plate 组织内唯一;推车编号同组织同仓库查重,重复返回 409)

DELETE/api/wms/tote-carts/{id}

删除拣货推车(有箱格在使用中→409;否则级联删箱格)。

GET/api/wms/tote-carts/{id}

推车详情:基本信息+推车当前停靠位置编码+箱格列表(含各箱格 license_plate/状态)。

PATCH/api/wms/tote-carts/{id}

编辑推车:cart_no/条码/启用状态/箱格数;改箱格数时全部箱格必须空闲(重新生成);可自定义箱格条码/编号(数量须与箱格数一致)。

GET/api/wms/tote-carts/{id}/labels

整车箱格条码+ZPL(供热敏打印/批量下载)。

周转箱/api/wms/totesGETPOSTPATCHDELETE5 个接口

GET/api/wms/totes

查询推车箱格列表(按格序号排序,可按推车过滤)

POST/api/wms/totes

手工为推车补建一个箱格(license_plate 组织内唯一、箱格编号同车唯一,重复返回 409)

DELETE/api/wms/totes/{id}

删除箱格(使用中→409)。

PATCH/api/wms/totes/{id}

编辑箱格:箱格号/license_plate/格口序号/状态(idle/in_use)。

GET/api/wms/totes/{id}/label

单个箱格的 license_plate 条码 ZPL(供热敏打印/下载)。

库存95 个接口

库存/api/wms/inventoryGETPOST17 个接口

GET/api/wms/inventory

库存查询(读 wms_inventory_balance 投影);支持 SKU 模糊、库位编码模糊筛选;计重产品返回重量三量(on_hand/allocated/available)。

POST/api/wms/inventory/adjust

库存调整:直接改账面数量,用于盘盈/盘亏/破损/丢失等纠错场景。只写台账(transaction_type=adjust),不碰余额投影。扣减时校验可用量,storage 库位增加库存时必须带托盘。

GET/api/wms/inventory/adjustments

库存调整单列表,可按仓库/货主/状态/单号过滤。

POST/api/wms/inventory/adjustments

新建库存调整单(草稿);仓库开启了自动审批则直接批准并落库存。

GET/api/wms/inventory/adjustments/{id}

库存调整单详情:表头 + 明细行(含调整前后值)。

POST/api/wms/inventory/adjustments/{id}/approve

批准调整单:draft → approved,并把每行的调整落到库存明细和台账。

POST/api/wms/inventory/adjustments/{id}/reject

驳回调整单:draft → rejected,驳回原因必填。

GET/api/wms/inventory/allocated

查已分配但还没拣的库存:哪些出库单占了哪些货、数量多少。订单行信息(SKU/名称/行量)经订单行表联查补齐(2026-10-24 D4 修复:订单行表无 organization_id 列,联查不得带该过滤,否则恒查空)。

GET/api/wms/inventory/detail

LP 粒度的库存明细查询(对标生产 WMS 的 Inventory Detail),支持多条件过滤。

GET/api/wms/inventory/expiry-alerts

临期/过期批次预警:未来 N 天内到期的批次列表。

GET/api/wms/inventory/export

导出库存明细为 CSV 文件(筛选参数与明细查询相同)。

GET/api/wms/inventory/import

下载库存明细批量导入的 CSV 模板。

POST/api/wms/inventory/import

库存明细 CSV 批量导入:传 CSV 文本,可先只校验不写入。引用(SKU/库位/客户/入库单)按 CSV 内码集合精确解析,与租户主数据量无关。写入以 detail 为事实源并同步 lot 累加、台账+余额投影(transaction_type=import、reference_type=inventory_import)与 serial 逐行登记,导入库存可直接分配/拣货。序列号一行一号(qty 必须为 1)、文件内与在库判重;track_serial 产品必须逐行带号、track_batch 产品必须带批次号;数量必须 >0。逐行错误以大白话返回,不整批失败(REQ-20261028-09)。

GET/api/wms/inventory/ledger

库存台账查询:库存的流水账(append-only),查每一笔库存变动(收货/上架/拣选/调整/盘点等)的数量变化和来源单据。

GET/api/wms/inventory/lots

批次库存查询(按到期日 FEFO 排序),支持按产品/批次/到期日/仓库过滤。

POST/api/wms/inventory/move

库存移动(手机移库):扫托盘或库位+商品 → 扫目标库位 → 确认移动,写移库台账。同步维护库存明细切片(2026-10-24 D5 修复):按客户切片先经 `applyAdjustDetailDelta` 出仓扣减/入仓增加(维度含 client/lot/pallet),再写 move 双腿台账——detail 与余额/台账三口径一致。可用量预检口径(2026-11-04 修复):按单据货主(client_id)聚合其在来源库位的全部归属(owner)切片可用量比对,与落账切片口径一致——同货主多归属切片不再被误拦(旧实现单行取数、多切片恒算可用 0),跨货主不串量。

GET/api/wms/inventory/summary

库存汇总:按(产品,状态,库存类型)聚合的数量统计。

调拨/api/wms/transfersGETPOSTPATCH11 个接口

GET/api/wms/transfers

库间调拨单列表查询:按调拨单号模糊、状态、调出/调入仓库、创建日期筛选;默认按创建时间倒序分页。

POST/api/wms/transfers

创建库间调拨单(单号 TRF- 开头,初始状态 draft)。2026-10-22 任务化口径:调出/调入仓库必须不同(同仓移位走移库任务 Move);一张单一个货主(client_id,3PL 模式必填);行分产品行(line_kind=product)与整托行(line_kind=pallet,可混单);from/to_location_id 改为可选(填了才校验属仓)——产品行来源库位在审批分配时确定、目的库位在收货执行时确定,行上 to_location_id 仅作预指定建议位。整托行校验托盘在调出仓、状态可用(received/staged)、未被其他未完成调拨占用、托上货主与表头一致,content_snapshot 以实托为准由服务端补齐。产品归属本组织校验、Location Group 品性硬约束保留。可用量不在建单拦截,在审批 release 分配时拦截并报明行。明细行创建失败时会自动回滚已创建的表头。存量同仓历史单的直办路径保留兼容。

GET/api/wms/transfers/{id}

调拨单详情:表头 + 明细行 + 分配片摘要 + 双任务摘要 + 时间线。scope 改为调出/调入任一仓命中即可见(任务化前只认调出仓,目的仓人员看不到单——已修)。

PATCH/api/wms/transfers/{id}

调拨单动作:cancel(取消)/ recall(在途召回,任务化新增)/ generate_tasks(补建任务,任务化新增)。

POST/api/wms/transfers/{id}/approve

调拨审批 = release:submitted→approved(通过)/rejected(驳回)。通过即执行分配预留(按表头货主切片落分配明细、可用量转已分配,取代旧的只查总量预检)并生成 Transfer Out 任务;分配不足时报错列明第几行缺多少、单据状态不动,可改量后重试。approved 字段必填且必须为 boolean——缺失或类型不对直接报错,绝不默认成驳回。免审批配置(组织级 transfer_require_approval=false)下建单即走同一 release 口径、不经本端点。scope:来源仓。

POST/api/wms/transfers/{id}/receive

调入仓全量收货确认:in_transit→completed;逐行写调拨台账双腿(调出库位在途减/调入库位可用加),明细行→done。任务化后落账已收敛到执行 lib 与 in-confirm 同一套腿/分配片口径:直办收货会一并完成该单已生成的未完成 Transfer In 任务(不会留下悬空任务);509 之前的存量在途老单走 lib 内兼容腿。scope 已改为**目的仓**(旧实现误查来源仓、只持目的仓范围的人收不了货——已修)。新调用方请用 POST /{id}/in-confirm(支持行级实收/破损/多出/实际上架位)。

POST/api/wms/transfers/{id}/ship

调拨全量确认发出:approved→in_transit;写台账双腿(已分配减/在途加)。任务化后落账已收敛到执行 lib 与 out-confirm 同一套腿/分配片口径(未分配先自动 release 分配再全量发出):直办发出会一并完成该单已生成的未完成 Transfer Out 任务,并按目的仓操作模式生成 Transfer In 任务。scope:来源仓。新调用方请用 POST /{id}/out-confirm(支持行级实发量/short 少发原因/装托)。

POST/api/wms/transfers/{id}/submit

调拨单提交审批:draft→submitted。

POST/api/wms/transfers/{id}/out-confirm

任务驱动确认发出(2026-10-22 任务化新增):按行提交实发量落账——已分配→在途双腿、short 未发量按分配片释放回可用、整托托盘状态转 in_transit;单据 approved→in_transit,并按目的仓操作模式生成 Transfer In 任务、完成 Transfer Out 任务。行状态闸:只有已分配(allocated)的行可发;**每一行都必须提交**(漏行直接报错列明缺行行号且不动账,没发出的行填 shipped_qty=0 并选少发原因);重复提交返回既有结果(幂等,不重复落账)。scope:来源仓。

POST/api/wms/transfers/{id}/in-confirm

任务驱动确认收货(2026-10-22 任务化新增):按行提交实收量落账——在途→目的仓上架位可用双腿、破损量成对落目的仓 damaged 账、多出量先入目的仓 hold 冻结待裁定;无未裁定差异时单据→completed,有短少/多出未裁定时→exception(破损-only 不进 exception,单据带 has_variance 标记正常关闭路径见设计口径)。未提交的行自动按短少登记差异(实收 0 派生);任务须全部行终态才完成。差异(短少/多出)必选原因码。重复提交幂等(行状态闸)。scope:**目的仓**。

POST/api/wms/transfers/{id}/resolve-variance

编辑供应商(白名单字段;code 不可改)。

库位/api/wms/locationsGETPOSTPATCHDELETE13 个接口

GET/api/wms/locations

查询库位主数据列表(多条件筛选+分页;`exclude_locked=1` 过滤被盘点锁定的库位)

POST/api/wms/locations

新建库位(编码在组织+仓库内唯一;无托盘模式仓库不能建 storage 库位;pick 类型自动建虚拟托盘;location_type 为已停用值(receiving/pack/ship)时拒绝 WMS_VALID_001——REQ-20261026-14,可新建类型口径见 wms-pure CREATABLE_LOCATION_TYPES / RETIRED_LOCATION_TYPES)

DELETE/api/wms/locations/{id}

停用库位(软删 is_active=false);有库存余额的库位不许停用。

GET/api/wms/locations/{id}

查库位详情全字段:编码、分区、类型、尺寸、温区、危险品、客户等。

PATCH/api/wms/locations/{id}

编辑库位:改名时同仓查重,温区/危险品值域校验;本次保存把 location_type 变更为已停用值(receiving/pack/ship)时拒绝 WMS_VALID_001(REQ-20261026-14;location_type 未变更的编辑——含不传、与整表单带回原值——不受影响,section/bin 不传即不改、原值保留)。

GET/api/wms/locations/{id}/files

查库位绑定的文件列表:每条带 1 小时有效下载链接(文档中心行换取链接,历史直传行走旧桶签名)。

POST/api/wms/locations/{id}/files

登记一个已上传到统一文档中心的文件到库位:先 POST /api/documents 直传,再调此接口登记 document_id。

GET/api/wms/locations/{id}/transactions

查库位的库存台账流水(分页,最新在前)。

GET/api/wms/locations/export

按列表筛选条件导出库位 CSV(最多 5000 行),直接下载附件。

POST/api/wms/locations/import

批量导入库位(前端已解析的 CSV 行):逐行校验,库位名同仓查重,返回每行导入结果;location_type 为已停用值(receiving/pack/ship)的行逐行拒绝(results[].ok=false 带行级 error),不占 code 名额、其余行照常导入(REQ-20261026-14)。模板列 bin/section 仍兼容读取(可选、不再推荐)。

GET/api/wms/locations/lookup

扫码查库位:按 code/barcode(须传 warehouse_id)或 id 直查,返回库位、托盘模式(storage 要扫托盘 / picking 免托盘)、库位上托盘和库存余额。

POST/api/wms/locations/auto-layout

3D 自动排布(批量):扫描指定仓库全部无坐标库位,用仓库的 layout_code_pattern 正则(命名分组 aisle/row/bay/level)解析编码,按坐标公式算出 3D 坐标写入 wms_location_3d。解析失败的返回 CODE_NOT_STANDARD、不写坐标;虚拟库位(location_type 不在白名单)跳过;已有坐标的绝不覆盖。建库位(POST /api/wms/locations)成功后也会自动触发单次排布(fail-open,失败不挡建库位)。

GET/api/wms/locations/layout-status

3D 排布状态统计:按仓库统计库位 3D 坐标覆盖情况——有坐标 / 待排布(无坐标且编码标准) / 编码不规范 / 虚拟库位四个计数,用于看自动排布覆盖率。

库位组/api/wms/location-groupsGETPOSTPATCHDELETE10 个接口

GET/api/wms/location-groups

查询虚拟库位组(Location Group)列表(名称模糊/组类型/标签/客户筛选,附客户名)

POST/api/wms/location-groups

新建虚拟库位组(VLG),可嵌套上架布局规则 arrangements(名称同组织查重,location_tags 必填至少 1 个)

DELETE/api/wms/location-groups/{id}

停用库位组(软删 is_active=false),记操作历史。

GET/api/wms/location-groups/{id}

查库位组(VLG)详情:全字段、staging 组名和 arrangements 排期规则。

PATCH/api/wms/location-groups/{id}

更新库位组:字段白名单 + arrangements 全量替换,自动记操作历史。

GET/api/wms/location-groups/{id}/history

查库位组的操作日志(最新 100 条):变更动作、快照。

DELETE/api/wms/location-groups/{id}/locations

批量把库位从库位组里移除。

GET/api/wms/location-groups/{id}/locations

查该组已加入的库位:库位 code、分区、库位类型。

POST/api/wms/location-groups/{id}/locations

批量把库位加入库位组:已存在的自动跳过。

GET/api/wms/location-groups/options

查库位组维护页的下拉数据:启用的客户、启用的 VLG、已用标签。

Location Group Mappings/api/wms/location-group-mappingsGETPOSTPATCHDELETE4 个接口

GET/api/wms/location-group-mappings

查询某仓库的产品品性→库位组(Location Group)映射列表,附组名与货主名

POST/api/wms/location-group-mappings

新建产品品性→库位组映射(组+货主组合查重;组必须属于传入或组绑定的仓库)

DELETE/api/wms/location-group-mappings/{id}

直接删除一条库位组映射。

PATCH/api/wms/location-group-mappings/{id}

更新库位组映射的属性:库位特性、ABC 等级或启用状态。

托盘/api/wms/palletsGETPOSTDELETE9 个接口

GET/api/wms/pallets

查询托盘列表(LPN 模糊/状态/仓库/入库单/库位筛选,附托盘明细行和库位名称)

POST/api/wms/pallets

创建收货托盘(LPN 系统自动生成或直接用工厂原厂标签;建完状态即 receiving 待收货)

DELETE/api/wms/pallets/{id}

删除托盘:仅组托中(building/receiving)且未写入过库存的可删;删空某入库单托盘且无收货事件时,入库单状态回退为 new。

GET/api/wms/pallets/{id}/label

取托盘 4x6 标签数据(LPN、仓库、入库单号、库位、明细行),供标签打印预览。

GET/api/wms/pallets/{id}/lines

查托盘明细行:商品 SKU/名称、数量、批次、效期、序列号。

POST/api/wms/pallets/{id}/lines

向组托中(building/receiving)的托盘加一行:商品、数量、批次、效期、序列号。

POST/api/wms/pallets/batch-generate

批量生成拣货用的空托盘 LPN(1–200 个):托盘状态 building、归属本仓库拣货暂存位(不存在自动创建),供拣货前备空托盘。

POST/api/wms/pallets/build

收货组托:建托盘(全局唯一 LPN)+明细行,序列号商品逐件建行并写台账追溯记录,返回 4x6 标签 ZPL。

GET/api/wms/pallets/lookup

扫托盘 LPN 查托盘内容:托盘(仓库/库位/商品)、明细行、序列号(托盘行与台账双源合并去重)。

移库任务/api/wms/move-tasksGETPOST7 个接口

GET/api/wms/move-tasks

移库任务列表(task_kind=move 移库 / replenishment 补货,默认 move);支持仓库/状态/执行人/任务号模糊筛选;每条附带来源/目标库位码、产品 SKU、执行人姓名。

POST/api/wms/move-tasks

桌面端创建移库任务:product 模式(按产品移动)/ pallet 模式(整托移动);库位支持传 id 或 code;创建时锁定来源库存。

GET/api/wms/move-tasks/{id}

移库任务详情:任务全字段 + from/to 库位码名 + 产品 SKU/名称 + 托盘 LPN + 执行人/创建人姓名 + 原因码本地化名。

POST/api/wms/move-tasks/{id}/cancel

取消移库任务(释放锁定)

POST/api/wms/move-tasks/{id}/drop

Step2 Drop(扫码校验+写台账,幂等)

POST/api/wms/move-tasks/{id}/pick

Step1 Pick(扫码校验+输实际数,幂等)

POST/api/wms/move-tasks/quick

手机临场移库(先做后补 task,幂等)

补货/api/wms/replenishmentGETPOST4 个接口

POST/api/wms/replenishment/{id}/drop

补货执行 Step 2:到目标拣选库位扫码放下,写台账(storage 区负/pick 区正);全部明细行完成则任务 completed,命中盘点锁定库位报错。

POST/api/wms/replenishment/{id}/pick

补货执行 Step 1:storage 区拣货(扫来源库位+商品+数量,扫码校验库位/商品与任务行一致、数量不超待补量);本步不写台账,只记拣选数+step log。

GET/api/wms/replenishment/candidates

人工补货候选清单(低于 min 的拣选位,dry-run,只列不建任务)。

POST/api/wms/replenishment/check

补货检查:扫描拣选位最低库存,低于 min_qty 自动生成补货任务;同一目标库位+商品已有未完成任务则跳过(幂等)。发运/拣选扣库存后可调用,可传 item_ids 限定范围。

盘点任务/api/wms/count-tasksGETPOST6 个接口

POST/api/wms/count-tasks

创建盘点任务(循环盘点/全盘/抽查),按账面库存生成盘点明细并锁定范围内库位;锁定冲突的库位会报 400

GET/api/wms/count-tasks/{id}

盘点任务详情 + 逐行明细(库位码、商品 SKU/名称已联查;盲盘隐藏账面数)。

POST/api/wms/count-tasks/{id}/approve

盘点审批:通过则已盘行变 approved 可过账;驳回则重盘(清空实盘数)。

POST/api/wms/count-tasks/{id}/enter-count

逐行录入实盘数量,系统自动算差异;严格模式下超阈值会先要求二次确认。

POST/api/wms/count-tasks/{id}/post

盘点过账:approved 行的差异写库存调整台账,任务完成并解除库位锁定。同步维护库存明细切片(2026-10-24 同族修复):每行先按差异经 `applyAdjustDetailDelta` 增减 detail(维度=任务仓/行库位/行产品/归属 client/available),再写 adjust 台账——detail 与余额/台账三口径一致。

POST/api/wms/count-tasks/abc

按商品 ABC 分类自动生成循环盘点任务(到期的、每仓一个任务)。

Pick Location Min/api/wms/pick-location-minGETPOSTPATCHDELETE5 个接口

GET/api/wms/pick-location-min

查询拣选位最低库存配置列表(附库位编码和商品 SKU+名称,补货候选的基准)

POST/api/wms/pick-location-min

新建拣选位最低库存配置(库位必须是该仓库的拣选区;同一库位+商品只能配一条,重复返回 409)

DELETE/api/wms/pick-location-min/{id}

删除一条拣选位最低库存配置。

PATCH/api/wms/pick-location-min/{id}

编辑拣选位最低库存配置:最低量/补货目标量(目标量不小于最低量,空=不限)。

POST/api/wms/pick-location-min/import

批量导入拣选位最低库存(前端已解析的 CSV 行):库位须为该仓启用中的拣选区、同一库位+商品不重复,逐行返回结果。

库区/api/wms/zonesGETPOSTPUT4 个接口

GET/api/wms/zones

Zone 主数据列表(Zone Picking 一期+温控配置):按 sort_order/zone_code 排序,行附 picker 绑定与成员库位数。温控四字段(报表 P3 B1 / CMP-05 一期,migration 748 加法列)随行返回:temp_min_c/temp_max_c(温区合格温度范围)、expected_inspections_per_shift(每班期望巡检次数,CMP-05 完整率 manual/import 分层期望)、device_interval_min(设备上报期望间隔分钟,device 分层期望);可空=未配(未配阈值的区不进 CMP-05 超限判定、完整率按回退口径)。权限隔离:登录+本组织成员(withWms),仅返回当前组织数据。

POST/api/wms/zones

新建 Zone。zone_code 归一化(trim+大写);唯一口径 (organization_id, warehouse_id, zone_code),同仓同码冲突 → ZONE_ALREADY_EXISTS,跨仓同 code 允许。温控四字段全部可空(口径同 GET 条目);temp_min_c/temp_max_c 须在 -60~80、两者都有值时 min<max(人话报错)。权限隔离:withWms(登录+本组织成员),warehouse_id 须为本组织仓库。

GET/api/wms/zones/{code}

Zone 详情:附引用该 zone 的库位数(location_count)与 picker 绑定数(picker_count);温控四字段随行返回(口径同 GET 列表条目)。跨仓同 code 时须传 ?warehouse_id= 精确定位(未传且多行 → ZONE_INVALID_INPUT)。权限隔离:withWms,仅当前组织数据。

PUT/api/wms/zones/{code}

编辑 Zone(PATCH 同实现)。zone_code 不可改(body 带不一致的 zone_code → ZONE_CODE_READONLY)。温控四字段按「出现在 body 中」判定:出现且为 null=清除该项(回落未配),未出现=保持现值;成对校验按生效值口径(出现以新值准、未出现回落现值)校验 temp_min_c<temp_max_c,温度范围 -60~80(校验口径同 POST 条目)。权限隔离:withWms,仅当前组织数据。

Marketplace Inventory/api/wms/marketplace-inventoryGETPOST5 个接口

GET/api/wms/marketplace-inventory

平台履约统一库存视图(SKU×位置矩阵):一个 SKU 一行,各平台位置库存分开展示,附跨平台可售/在途汇总

POST/api/wms/marketplace-inventory/sync

FBA 库存同步:按本组织逐位置调用同步引擎,拉取 Amazon 各 inbound 位置库存并 upsert(平台履约 P0)

POST/api/wms/marketplace-inventory/locations

建/绑平台履约位置(REQ-20261025-39 加法端点):按 (组织, client, platform, location_code) 幂等建行或回绑 connection_id,此前全仓无代码创建 wms_marketplace_locations 行、同步无对象;body {platform(默认 amazon_fba), location_code?, location_name?, country?, connection_id?, client_id?(3PL 必填)},连接给了必校验属本组织且 channel_code 与 platform 一致;client 解析与 GET 同口径

POST/api/wms/marketplace-inventory/tiktok-fbt/push

TikTok FBT 手工补货推送(Andy 2026-10-16 批准推模式上线:显式手动,不进 cron):{location_id 必填, warehouse_id 必填(缺失 400,绝不默认写第一仓), items 可选(不传按自有仓实时快照自动生成), dry_run 可选(true=只预览)};无 key 走 mock 标注"模拟";每次执行写 wms_marketplace_push_logs 审计

GET/api/wms/marketplace-inventory/tiktok-fbt/warehouses

查 TikTok 侧仓库列表(补货推送弹窗的选仓库下拉用):有 key 时真实拉取,无 key/模拟位置时返回固定模拟数据并标注。

任务与工单75 个接口

任务/api/wms/tasksGETPOSTPATCH21 个接口

GET/api/wms/tasks

统一任务列表(入库/上架/拣选/补货/盘点/移库/装车任务合并展示,支持超时筛选和行进度)

GET/api/wms/tasks/{id}

任务详情:任务头+明细行(入库收货行/补货行/拣选行+拣选方式)+创建人/指派人姓名。

PATCH/api/wms/tasks/{id}

更新任务状态(pending→in_progress→completed/cancelled;另 assigned→in_progress/cancelled,REQ-20261027-03:已指派任务点「开始任务」走此流转并写 started_at)、负责人、入库方式;首次收货提交后入库方式锁定不可改。桌面端任务管理用,移动端走各自执行流。负责人改派:仅 pending / in_progress 可改派或取消指派,completed / cancelled 回 409 `WMS_STATE_001`;改派目标须为本组织成员(`platform_organization_members`),外组织/不存在的用户回 `WMS_VALID_001`(2026-10-21 起,对齐越库 PATCH 口径);assignee 实际变化时同步 `assigned_at` / `assigned_by`(取消指派时清空),往 `wms_task_step_log` 追加一条改派留痕(step_name='改派'、payload.kind='assignee_change'、含 from/to 姓名快照;2026-10-21 起 payload 加法带 `from_assignee_email` / `to_assignee_email`,供时间线对同名账号消歧,旧留痕无此字段),并经统一通知中心给新负责人发 `wms.task.assigned`(取消指派不发)。Labor 护栏(2026-11-01 批一,REQ-20261031-71):task_type=labor 的行在 Body 含 status 时回 409 `WMS_STATE_001`,文案指路计时页(人工任务的状态只能在计时页开始/结束,直接改状态会留下永不关闭的计时条目);labor 改派照常放行,进行中/已暂停行改派只换负责人、在途计时的收尾仍归原执行人。

POST/api/wms/tasks/{id}/offload

入库任务 Step 1 卸货:记录卸货类型+可选备注,任务 pending→in_progress,记一条 step log。

GET/api/wms/tasks/{id}/photos

任务照片存档列表(卸货过程与货物状况照片随任务存档);文档中心迁移后 photo_url 为查询时换取的 1 小时有效签名链接,历史直传行原样返回。

POST/api/wms/tasks/{id}/photos

上传任务照片(multipart/form-data:file 必填+caption 可选);文件转存统一文档中心,元数据记任务照片表。

POST/api/wms/tasks/{id}/receive-complete

入库任务完成:校验任务为 receive/in_progress 且入库单所有明细行已收完→入库单 received→任务 completed;auto_putaway 开启时自动生成上架任务并关联收货单托盘。

POST/api/wms/tasks/{id}/close

门面统一 Close 入口(WES 一期前置批 A,2026-11-01,D83 §6.8):facade 注册表 capabilities.closeDispatch 声明 + `lib/task-close.ts` 行为注册表分发,新增可关闭类型只加登记、不改本入口。完成口径以 pick complete 为模板(原因码必填、剩余按已执行量结算、step log 留痕、通知原 assignee),各类型端点各自执行。未登记真实 close 实现的类型如实回 400,不假接。

POST/api/wms/tasks/{id}/release

人工直放(WES 一期批 1-C,2026-11-01,D83 §6.1 M1 释放门):主管在任务详情/Task Query 点「立即释放」时调用。写 `release_at = now()`(migration 765)+ step log 记字典码 `wes.release.manual` + 通知原 assignee(通知类型 `wms.task.released`)。只对 wms_tasks 原生任务行;已释放重复调用 = 幂等回放(`released=false`,不重复留痕/通知);已开始回 409(不需要释放)、已结束回 409;移库/补货(wms_move_tasks)与投影三类不在释放门覆盖面 → 404。响应 `{ task_id, task_no, released, release_at }`。release_at 的写方只有本端点与推进器 cron `wes-release-propeller`(每分钟,统一入口 `/api/cron/run?task=wes-release-propeller`,按规则引擎 `wms.release` 域策略推进),生成方经统一入队口不写。

POST/api/wms/tasks/{id}/claim

任务领取(双路径按 claimant_type 分流)。**device/station=WES 租约领取**(D83 §6.3,REQ-20261101-16):领已释放任务、落 wms_task_claims 租约行(TTL 默认 30 分钟),已被领 409、未释放 409。**human=作业员指派型领取**(2026-11-02,REQ-20261102-15 待领任务池):仅 assignee_id IS NULL 且 status=pending 可领;单条条件 UPDATE 原子抢领,置 assignee_id=本人/assigned_at/assigned_by、status 保持 pending;成功 `{ task, already_mine }`(本人名下重复领幂等回 already_mine=true);输家 409 `WMS_STATE_001`(人话「刚被别人领走了」);任务有未过期 WES 租约 409(设备/工位占用);claimant_id 只许缺省或本人(替别人领回 400 指路改派);数据范围按任务仓 assertDataScope(同 PATCH 改派口径,跨组织 404);留痕 step log `task.claimed`(payload.kind=task_claim)。

GET/api/wms/tasks/{id}/claim

查任务当前有效 WES 租约领取(过期读时判定并惰性关账);无有效领取时 data.claim=null。指派型领取(human)不落租约行,本端点只反映租约占用。

POST/api/wms/tasks/{id}/claim/renew

WES 租约续租(同主体幂等顺延 expires_at);human 回 400 人话(指派型领取没有租约,不用续租)。

POST/api/wms/tasks/{id}/claim/release

WES 租约主动释放(关账 voluntary,任务回池可再领);human 回 400 人话(取消指派走主管改派,不走释放)。

POST/api/wms/tasks/{id}/claim

任务领取(WES 一期批 1-D,D83 §6.3 M3 领取原语;迁移 766 `wms_task_claims`):设备/工位领取已释放(release_at 非空)未终态任务。Body:`claimant_type` 必填(`device`\

GET/api/wms/tasks/{id}/claim

查任务当前有效领取(读时判定:未关账且 expires_at 未过才有效;顺带惰性关账过期行)。无有效领取回 `data={ claim: null }`;领取表未就绪(migration 766 未应用)时与写路径统一回 `WMS_SERVER_001` 不可用,不装成无领取(批 1 修复 P3-1/P3-4)。

POST/api/wms/tasks/{id}/claim/renew

续租领取:Body `claimant_type`/`claimant_id` 必须与在账领取同主体(单条条件 UPDATE 四条件原子校验:组织+任务+同主体+未关账未过期)。同主体重复续租幂等(到期顺延 ttl);异主体 409;无领取 404;已过期 409(回 expired 并已惰性关账,需重新领取)。落 step log `task.claim_renewed`。

POST/api/wms/tasks/{id}/claim/release

主动释放领取:同主体条件 UPDATE 关账(closed_reason=voluntary)。异主体 409;无领取 404。释放后任务可被他人领取。落 step log `task.claim_released`。

GET/api/wms/tasks/{id}/steps

任务执行台账(step log,append-only):手机端提交明细+时间线事件;每条含步骤名/动作/结果/payload/操作人/时间,location_id 已丰富为库位编码。排序口径(2026-11-01 WES 前置批 B,D83 §6.7):created_at 升序+id 升序,每行带 display_no 展示序号(1..N 按此排序现算);step_no 为存量原值字段、不作排序键。step_name 原样返回:新写为事件字典码(packages/lib/src/wes/event-codes.ts)、存量为自由文本,显示层 stepNameLabel 双轨处理。

POST/api/wms/tasks/{id}/steps

追加任务执行台账 step log(只追加不改),step_no 按该任务现有最大+1(存量写入侧口径)。可选 idempotency_key(2026-11-01 WES 前置批 B,D83 §6.7,migration 764):带 key 时先按 (organization_id, task_source, task_id, key) 完整键复核,命中回放既有行;insert 唯一冲突后再复核回放,不盲重试。step_name 新写建议用事件字典码(如 wes.job.completed、pick.started)。

GET/api/wms/tasks/{id}/orders

拣选任务关联的出库单列表(任务详情页 Order List 区):默认按 wms_pick_task_lines.shipment_id 取单并汇总每单拣选进度;**波次回退(2026-10-21)**:Dispatch Setting 放行建的 pick task 不写 pick_task_lines,此时若 task.source_doc_type='wave' 则按 wms_waves.shipment_ids 取单,qty_to_pick 用 wms_order_lines.ordered_qty 汇总、qty_picked=0。每行带 line_count(该单订单行数,2026-10-21 加法字段)。

GET/api/wms/tasks/stats

任务统计:open_total(未完成总数)+ by_type 分类型未完成计数(REQ-20261023-62/-63,手机 Tasks 计数用)。**2026-11-02(REQ-20261102-15)**:加 `unassigned=1`——全部计数改按未指派(assignee_id IS NULL)圈定且 move/投影计数恒 0;同传以 unassigned 为准。注:这是「未指派开放任务」宽口径(by_type 含 in_progress 未指派行),池的 pending-only 权威计数走 GET /api/wms/tasks?unassigned=1&status=pending 的 meta.total。鉴权:组织成员(withWms)。

人工任务/api/wms/labor-tasksGETPOST11 个接口

POST/api/wms/labor-tasks

为项目创建一个人力任务(一个任务只派一个人,多人就建多个)

GET/api/wms/labor-tasks/<built-in function id>

人工任务详情(任务+最新计时条目+分段+暂停原因码)(2026-11-01 Labor 批一,REQ-20261031-71:内部改背 wms_tasks+扩展表 wms_task_labor_ext,URL/请求字段/响应字段与 status 旧词口径全部不变)

POST/api/wms/labor-tasks/{id}/cancel

取消人工任务(任务标准化一期 2026-10-22 新增)。Body:`{ reason* }`(原因必选)。仅 `status=created` 可取消(已开始走 end/审核流);成功后往统一 step log 写摘要行(task_source=`wms_tasks`(2026-11-01 批一并表后口径;并表前为 `wms_labor_tasks`)、payload.kind=`task_cancelled`),响应含 `step_log_failed` 标记台账是否写入失败(失败不回滚取消)。错误:缺 reason → WMS_VALID_001;非 created 态 → WMS_STATE_001。labor 无上游单据,为《Close 设计》「cancel 跟单据走」的例外二(已互引备案)。权限:宽松默认。

POST/api/wms/labor-tasks/{id}/end

结束劳务任务计时:任务须为 in_progress/paused,自动算净工时并转主管待审核;完成后尝试自动完成所属项目。

POST/api/wms/labor-tasks/{id}/pause

暂停劳务任务计时:任务须为 in_progress,暂停原因必填。

POST/api/wms/labor-tasks/{id}/resubmit

驳回后重新提交:任务须为 completed 且最新一轮计时被驳回,开新一轮计时(旧驳回记录保留审计,幂等)。归属口径与 start 相同(本人或主管代提,代提留痕,他人非主管 403)。

POST/api/wms/labor-tasks/{id}/resume

恢复暂停中的劳务任务计时:任务须为 paused。

POST/api/wms/labor-tasks/{id}/review

主管审核劳务工时:通过则计入汇总,驳回则退回并留备注。

POST/api/wms/labor-tasks/{id}/start

开始劳务任务计时:任务须为 created 状态,创建一条计时记录。计时归属护栏(2026-11-01 批一 L-G24):已指派任务只能由被指派人本人启动;主管可代启,代启在任务时间线留痕并双记被指派人与操作人,工时条目的执行人记实际操作人;他人非主管回 403 WMS_FORBIDDEN_001。

GET/api/wms/labor-tasks/pending-review

主管查待审核的工时记录:已结束且 review_status=pending 的计时,净工时超 12 小时标异常,附任务/项目/客户信息。(2026-11-01 批一:待审识别改按计时条目 task_kind=labor,响应契约不变)

GET/api/wms/labor-tasks/{id}

查单个劳务任务详情:任务全字段、当前计时条目、计时分段和暂停原因码。

Labor Indirect/api/wms/labor-indirectGETPOSTPATCH9 个接口

GET/api/wms/labor-indirect/codes

间接工时类别列表(L-G15,REQ-20261101-06):字典表 wms_labor_indirect_codes(迁移 745);首次读取时按组织确保预置五码存在(代码常量为单一事实源:training/cleaning/maintenance/meeting/count_support,含六语名)

POST/api/wms/labor-indirect/codes

新建组织自定义间接工时类别(L-G15)

PATCH/api/wms/labor-indirect/codes/{id}

更新间接工时类别(L-G15):系统预置类别不能改名(服务层校验),可停用/启用与调序

GET/api/wms/labor-indirect/current

我进行中的间接工时条目(L-G15),无则 data=null

GET/api/wms/labor-indirect/entries

间接工时条目列表(L-G15,分页):响应附类别 code/name 与工人显示名(永不显示 UUID 当名字);净工时超 12 小时的已结束条目标 abnormal(提醒主管,与项目工时审核同口径)

POST/api/wms/labor-indirect/start

开始间接工时(L-G15):互斥口径——本人已有任务计时或另一类间接计时在进行时 409 人话提示;同一类别重复提交幂等返回既有条目

POST/api/wms/labor-indirect/stop

结束本人进行中的间接工时(L-G15):结束后落 net_seconds、review_status=pending 待主管审核

POST/api/wms/labor-indirect/{id}/review

审核间接工时(主管,L-G15):[id] 为条目 id(wms_labor_time_entries.id);护栏——审核人≠条目工人且须主管资格(isEligibleApprover 单一事实源,fail-closed),驳回必须填原因;通过的条目即 L-G04 对账的 indirect 账

POST/api/wms/labor-indirect/{id}/force-stop

主管强制结束进行中的间接工时(批零 WS-C,REQ-20261108-09,D133 §2.3):无 Body;条目须 task_kind=indirect 且未结束,须主管资格(fail-closed,无自停限制);结束时刻落 end_time+net_seconds、review_status 保持 pending 转待审;留痕写 wms_audit_log(action=wms.labor_indirect.force_stop),审计写失败不回滚、响应带 audit_failed=true

Task Takeover Requests/api/wms/task-takeover-requestsGETPOST5 个接口

GET/api/wms/task-takeover-requests

任务接管申请列表(2026-10-21 新增,Take Over Task 一期)。Query:`role=approver`(默认,待我审批+我处理过的)/ `role=requester`(我发起的);`status` 可选过滤(pending/approved/declined/cancelled/invalidated);`?lang=` 本地化错误文案。响应行 = 申请全字段 + `requester_name`/`from_assignee_name`/`decided_by_name`/`task_status`(源任务当前状态显示口径),approver 视角另带 `meta.pending_count`(待我审批数)。仅返回与当前用户有关的申请(组织隔离 + 当事人收窄)。

POST/api/wms/task-takeover-requests

发起接管申请(2026-10-21 新增)。Body:`{ task_no* }`(人类可读编号,wms_tasks 与 wms_move_tasks 两源按编号定位,跨仓可申请)。校验:任务已结束 409 `TAKEOVER_TASK_ENDED`;盘点任务豁免 409 `TAKEOVER_COUNT_TASK`(2026-10-24,REQ-20261023-21①:count 任务不走接管,换人由主管重新指派);无 assignee 409 `TAKEOVER_NO_ASSIGNEE`;申请自己的任务 409 `TAKEOVER_OWN_TASK`;已有 pending 409 `TAKEOVER_ALREADY_PENDING`;查不到 404 `TAKEOVER_TASK_NOT_FOUND`。成功发通知 `wms.task.takeover_request`(category=approval)给当前 assignee。

GET/api/wms/task-takeover-requests/{id}

接管申请详情(2026-10-21 新增)。仅当事人(申请人/被申请的 assignee)可见,非当事人 403 `TAKEOVER_NOT_PARTY`。响应多带 `my_role`(approver/requester/both)与 `takeover_exempt`(2026-11-02 新增,REQ-20261102-31:盘点任务豁免标记,true 时批准必然回 409 `TAKEOVER_COUNT_TASK`,客户端据此前置提示并收起批准钮;列表行同带)。

POST/api/wms/task-takeover-requests/{id}/cancel

申请人撤回 pending 申请(2026-10-21 新增)。非申请人 403 `TAKEOVER_NOT_PARTY`;非 pending 409 `TAKEOVER_NOT_PENDING`。置 status=cancelled(不发通知)。

POST/api/wms/task-takeover-requests/{id}/decide

审批接管申请(2026-10-21 新增)。Body:`{ decision*: 'approve' \

Issue Reports/api/wms/issue-reportsGETPOST4 个接口

POST/api/wms/issue-reports

登记无任务异常上报(REQ-20261024-17):{ description?, warehouse_id?, with_photo? },description 与照片至少其一,否则 400 WMS_VALID_001。落 wms_issue_reports(status=open);任务内异常仍走 tasks/{id}/steps,不经此端点

GET/api/wms/issue-reports

无任务异常上报列表(status=/warehouse_id=/page=/page_size=;created_at 倒序;含 photo_count、reported_by_name)

POST/api/wms/issue-reports/{id}/photos

上报照片上传(multipart:file*,≤10MB、单条最多 5 张,超限 400 **WMS_LIMIT_001**——REQ-20261102-33 起专用码,原 WMS_VALID_001):走统一文档中心(ref_type=issue_report),doc id 记入上报行 photos 数组;同字节重传幂等(REQ-20261024-08 桥层处理)。上报不存在 → 404

GET/api/wms/issue-reports/{id}/photos

上报照片列表 [{ id, photo_url(1 小时签名链接,读时现换) }]

工单/api/wms/work-ordersGETPOST10 个接口

GET/api/wms/work-orders

查询装配工单列表(附成品 SKU/名称);`pending_count=1` 只返回当前用户的待办工单数(手机 More 菜单角标用)

POST/api/wms/work-orders

手工创建装配工单(只支持 MTS 备货生产 / 拆解;MTO 由订单自动触发,不能手工建)

GET/api/wms/work-orders/{id}

工单详情:工单头+成品 SKU/名称+组件需求(含组件 SKU/名称丰富)+lot 追溯记录。真拣选一期加法字段(2026-10-21):staging_location_code / staging_warehouse_id;components[] 每行带 track_batch/track_serial、short(短拣 {qty, reason_code}|null)、lines[](拣选明细:line_id/status/source_location_code/suggested_location_code/suggested_location_type/pallet_lpn/lot_no/serial_nos/qty_planned/qty_picked/qty_returned/short_reason_code);顶层 leftover[](暂存未用料:{component_item_id, qty, lines[{line_id, qty, serial_nos, returnable}]})。老字段全保留。

POST/api/wms/work-orders/{id}/cancel

取消工单(桌面端专用路径;手机端不给 Cancel)。真拣选一期起:已开工工单(picking/组装/质检)cancel 先结算再落终态——已拣未消耗全量原路退回、显式传入的实际消耗记账、未拣建议行作废,reason 落 close_reason_* 留痕;draft 直接取消(无库存动作)。2026-10-21 review P2-2:已开工工单 reason_code **必填**(force_close 分类,服务端强制校验,与手机 Force close 同口径;桌面端已改弹窗必选);draft 原因可省,带了则校验并留痕。Body:{ reason_code?, reason_note?, components?: [{component_item_id, qty_consumed}] }。响应带 leftover 与 leftover_unreturned_count。

POST/api/wms/work-orders/{id}/complete

工单完工/关闭结算(真拣选一期重做):报完工数/报废数,按实际消耗记账+lot 追溯;MTS 成品待入库(调上架),MTO 成品直接关联订单出库。结算口径:components 可选——某组件 qty_consumed 留空 = 服务端默认按已拣数全量消耗;消耗上限 = 本工单在暂存位的台账净量(按工单 reference 聚合),且受 BOM 可装量约束(以最终消耗量按单件用量反算——2026-10-21 review P2-1 修正:显式压低 qty_consumed 则可装量同步变小,不能再以已拣数绕过),超量拦截并点名组件;**完工同请求内把未消耗组件按原拣出行原路退回来源库位**(响应 leftover 明细,退不回的行计 leftover_unreturned_count)。支持 Force close(手机主页 Close/Force close 走本端点):force_close=true 时 picking 阶段也可关闭(强制零产出零消耗、已拣全量退回、未拣建议行作废),reason_code 必填(force_close 分类)并落 close_reason_code/close_reason_note、发通知 wms.task.force_closed。

POST/api/wms/work-orders/{id}/pick-component

记录组件拣选;工单状态必须为 picking。真拣选一期三分支:①带 line_id = 按建议行拣:校验(盘点锁/同仓/超量 1.1 倍/storage 位托盘必传且在位/lot 必带且校验可用量/SN 个数=数量且不重复)→ move 两腿过账(来源→工单暂存位,reason=assembly_pick,reference=工单)→ 回写拣选行与组件汇总;行级幂等(已 picked 重提返回既有汇总);部分拣后自动补一条新建议。②无 line_id 但带 source_location_id = 自由拣:建临时建议行走同一过账路径。③无 line_id 且无 source_location_id = legacy 过渡分支(只累加 qty_picked、不过账,响应 legacy_mode:true;一个发布周期后下线)。

POST/api/wms/work-orders/{id}/pick-skip

Next 跳过当前建议库位:建议行置 skipped、写跳过日志(复用 wms_pick_suggestion_skips,task_id=工单 id、line_id=拣选行 id),并按分配顺序给出下一条未建议过的库位建议;没有更多库位时 exhausted=true(工人可自由拣或短拣结清)。

POST/api/wms/work-orders/{id}/short-confirm

短拣结清 / 继续拣重开。confirm(默认):把组件未拣缺口按短拣结清——开放建议行置 short、组件落 short_qty/short_reason_code/short_confirmed_by/short_confirmed_at(工人确认即可放行 start-assembly,不加主管环节)。reopen:清短拣留痕并重新生成建议(历史 short 行保留)。

POST/api/wms/work-orders/{id}/start-assembly

工单进入装配:门槛 = 每个组件已结清(qty_picked>=qty_required 或已短拣确认);未结清时报错并在响应 details.unsettled 给出明细。响应带 shortages 短拣摘要(哪些组件短了多少、什么原因)。work_center_id 传入时沿用既有登记逻辑(开工时间/工作中心工时);工单尚无暂存位时以工作中心绑定位补落定。

POST/api/wms/work-orders/{id}/start-picking

工单进入拣选(真拣选一期):先落定货主(入参 client_id > 工单已有 > MTO 来源订单 client_id)与组装暂存位——解析链:入参 staging_location_id > 工单已落定 > 已绑工作中心 staging(请求带 work_center_id、或工单已有工作中心且其绑定唯一指向)> 仓库默认组装暂存位;都无 → 报错拦下(大白话:先去仓库设置里选默认组装暂存位,或在工单上选一个)。落定后按与订单拣选统一的策略解析链(全局规则 W-K-S2 为底、客户 allocation_strategy 已配例外时覆盖,例外由 allocatePickLocation 内部单点注入)为每个组件生成逐行建议(wms_work_order_pick_lines:库位+计划量,storage 位带建议托盘 LPN、批次组件按 FEFO 带 lot),响应直接带建议明细供手机执行页渲染。组件拣选在工单内跟踪,不经过 shipment 耦合的拣选任务。

项目/api/wms/projectsGETPOSTPUTDELETE8 个接口

GET/api/wms/projects

查询 VAS 项目列表(可按货主/状态筛选,附货主编码与名称)

POST/api/wms/projects

新建 VAS 项目(增值服务项目,如贴标/换包装)

GET/api/wms/projects/{id}

项目详情:基本信息+人工任务列表(含工时/审核状态)+物料清单+工时汇总(仅 approved)。项目对象含 warehouse_id(可空,2026-11-01 批一新增:项目所属仓库)。

PUT/api/wms/projects/{id}

设项目默认计费费率(REQ-20261108-16);Body:`{ billing_rate_amount: number\

POST/api/wms/projects/{id}/rate-overrides

新增 task_kind 费率覆盖行(版本式,不改旧行;REQ-20261108-16);Body:`{ task_kind*, rate_amount*, currency?, effective_from*, effective_to? }`;覆盖解析优先于项目默认(按条目发生日取生效行)。覆盖行清单随项目详情 `billing.overrides` 返回

POST/api/wms/projects/{id}/reopen

重新打开已完成的项目(REQ-20261026-13 新增)。无 Body。项目下全部 labor task 终态后项目自动 `completed`,此前无重开入口、项目永久锁死不能再建任务;本端点 `completed → active` 并清 `completed_at`(带状态并发护栏),留痕写 `wms_audit_log`(action=`wms.project.reopen`、target=`wms_projects`、details 含原 completed_at)。响应 `{ id, status: 'active', audit_failed }`(留痕失败不回滚重开、如实标记)。错误:项目非 completed → WMS_STATE_001(人话「项目正在进行中,不需要重新打开」);并发状态已变 → WMS_STATE_001(提示刷新重试)。重开不触发项目自动完成判定(其触发点只在 labor task 的 end/cancel 状态迁移)。权限:宽松默认。

POST/api/wms/projects/{id}/materials

给项目添加物料用量(产品须为 material/supplies 类型,自动带计费价快照;item_type 合法集为 product/material/supplies——packing_material 已由 migration 540 改名 material,项目物料允许值以单一事实源常量为准)。

DELETE/api/wms/projects/{id}/materials/{mid}

删除项目的单条物料用量。

物料清单/api/wms/bomsGETPOSTPUT7 个接口

GET/api/wms/boms

查询 BOM(物料清单)列表,附成品 SKU/名称和组件行数,最多返回 200 条

POST/api/wms/boms

为成品新建一个 BOM(版本号自动+1,初始 draft;组件不能是成品自己,数量必须大于 0)

GET/api/wms/boms/{id}

BOM 详情:成品 SKU/名称 + 明细行(每行带组件 SKU/名称)。

PUT/api/wms/boms/{id}

编辑 BOM:draft 可改明细;状态流转 draft→active→archived(draft 生效时旧 active 自动归档)。

POST/api/wms/boms/{id}/copy

把某个 BOM 的明细复制成另一个成品的新 BOM(v1,draft 状态)。

POST/api/wms/boms/{id}/new-version

基于现有 BOM 建新版本(draft,版本号 max+1;不传明细则复制原明细)。

GET/api/wms/boms/where-used

反查某个组件被哪些 BOM 使用(用量清单反向查询)。

3D 可视化与 WES48 个接口

3D 可视化/api/wms/visualizationGETPOSTPATCHDELETE24 个接口

GET/api/wms/visualization/bin-locate

3D 库位定位查询:按 code 模糊搜 / 精确 / 库位组 / 库位类型,返回库位 3D 坐标 + 楼层(meta=1 时只返回去重库位类型列表)。搜索定位扩展(REQ-20261106-27):suggest=1 联想模式与 zone/sku/lpn 解析模式(口径见 D120 §14.3);解析参数与 suggest 互斥(suggest=1 时解析参数忽略),sku 与 lpn 同传以 lpn 为准。

GET/api/wms/visualization/floor-stats

某仓库全部楼层的库存概况(每层总库位/有货库位/占用率),读快照表(cron 每 5 分钟刷)。

GET/api/wms/visualization/layout

取某仓库某楼层的 3D 布局与库存占用聚合(货架级聚合 + 全部库位数组);无 published 布局 → 404。

POST/api/wms/visualization/snapshot/refresh

WMS 3D 快照按需刷新(2026-10-19 账单优化:替代停用的 5 分钟 cron):body {warehouse_id 必填,layout_id 可选},取最新 published 布局→逐楼层现场算聚合→写回 wms_visualization_snapshots;返回 {warehouse_id, layout_id, floors, refreshed, failed, errors[], computed_at};登录+组织隔离鉴权(与 floor-stats 一致);快照是组织级共享缓存,始终全组织口径计算

POST/api/wms/visualization/layouts

生成 draft(action=generate,调 wms_generate_3d_layout)/发布 draft(action=publish),Phase 1

DELETE/api/wms/visualization/layouts/{id}

删除 draft 布局版本(3d 行级联删除);cleanup_locations=1 时清理该版本生成的无业务引用库位行。

GET/api/wms/visualization/layouts/{id}

布局版本详情(编辑器预览):布局信息 + 按货架组聚合的包围盒;bins=1 时附全部库位行。

PATCH/api/wms/visualization/layouts/{id}

拖拽微调保存(仅 draft):整组平移/旋转/缩放、单个库位微调、删除货架组(含无业务引用的库位主数据清理)。

GET/api/wms/visualization/layouts/{id}/doors

仓库门列表(编辑器三档升级):取仓库门的坐标与朝向边,供编辑器在建筑外形上渲染门洞。

POST/api/wms/visualization/layouts/{id}/doors

新增门(仅 draft,409):edge=N/S/E/W,门到 building polygon 边界<2m;Phase 2

DELETE/api/wms/visualization/layouts/{id}/doors/{doorId}

删除仓库门(仅 draft,非 draft → 409)。

GET/api/wms/visualization/layouts/{id}/zones

区域列表(含多边形顶点),供编辑器渲染底图。

POST/api/wms/visualization/layouts/{id}/zones

新建区域(仅 draft,published/archived 409):zone_type+polygon(≥3顶点)校验,颜色按类型默认;Phase 2

DELETE/api/wms/visualization/layouts/{id}/zones/{zoneId}

删除区域(仅 draft,非 draft → 409;已生成的货架/库位不受影响)。

PATCH/api/wms/visualization/layouts/{id}/zones/{zoneId}

修改区域:改名/改色/改顶点/改类型(仅 draft,非 draft → 409)。

POST/api/wms/visualization/layouts/{id}/zones/{zoneId}/generate

Zone 内按货架类型自动生成货架组(selective/drive-in/flow/floor-stack,自动避让 aisle 区),link-or-create 库位;Phase 2

POST/api/wms/visualization/layouts/duplicate

复制某个布局版本为新的草稿:新版本号=当前最大+1,名字=原名+" - 副本";3D 坐标按新 layout_id 复制一份;新草稿可预览/编辑/发布。

POST/api/wms/visualization/layouts/generate

3D 布局自动生成:按表单参数(仓库长宽、货架排数、每排货架数、层数、列数)算出全部库位坐标,一次性创建库位行+draft 版本+3D 坐标行;仅限还没有库位的空仓库。

POST/api/wms/visualization/layouts/import

Excel 导入布局:前端按模板列解析校验后把货架组行数组 POST 到这里,服务端生成 draft 版本;库位编码已存在则复用(link-or-create),适用于空仓库和已有库位仓库。

POST/api/wms/visualization/layouts/rollback

回滚到某个已归档(archived)布局版本:该版本→published,当前 published→archived;只接受 archived 版本(draft 的发布走 layouts 的 publish 动作)。

GET/api/wms/visualization/layouts/versions

取某仓库全部 3D 布局版本:按版本号倒序,含每版状态(draft 草稿/published 已发布/archived 归档)/货架组数/库位数。

GET/api/wms/visualization/location/{id}

单个库位的库存明细(3D 库位点击抽屉数据源)+ 3D 坐标 + 相邻库位。

GET/api/wms/visualization/pick-path

按拣货顺序返回 3D 拣货路径点(输入订单或拣选任务二选一)+ 预计距离;route_mode=aisle 时沿通道 A* 路径。

GET/api/wms/visualization/pick-path/validate

拣货顺序验证:沿通道距离对比"系统顺序"与"启发式最优顺序"(NN+2-opt),返回 extra_distance_m/extra_pct/verdict。

WES 执行/api/wms/wesGETPOSTPATCH24 个接口

POST/api/wms/wes/hub-heartbeat

Hub 适配器清单心跳 ingest(WES 一期批 2-F,2026-11-01,REQ-20261101-16,D83 §6.5 M5):机器客户端简单 JSON(非业务信封)。鉴权仿 diag 通道先例:`Authorization: Bearer <publishable key>` 通道门+`x-hub-id: <device_hubs.id>` 身份锚(组织取 Hub 行,上报自报组织不采信;Hub 未知回 401 `HUB_UNKNOWN`)。body `{adapters: [{code, version, capabilities[], commissioned}], devices: [{device_key, name, device_type, adapter_code, capabilities, status, config?}]}`(adapters ≤200、devices ≤500)。云端把清单落成 devices 只读镜像(source='hub',对齐键 config.hub_device_key):清单哈希与对账状态(`wes_hub_mirror_state`)一致时只推进 last_seen_at;不一致即告警(state.last_alert)+按本次上报全量重建镜像(只动本 Hub 的 hub 镜像行)。响应 `{ok, hash, mismatch, rebuilt, created, updated, removed}`。心跳超时(规则 `wms.wes` 域码 W-E-X2,默认 5 分钟)的 Hub 设备由读面按 offline 归一(hub-mirror 单点口径)。

POST/api/wms/wes/hub-device-events

Hub 机器通道事件摄入单点(B3,2026-11-05,REQ-20261105-14,D118 §6.3/D-5):Hub outbox 事件回流的唯一入口,与登录面 device-events 共用 ingestDeviceEvent(去重/状态迁移/step log/六态/节流同口径),取代 Hub 直写 wes_device_events 表+自 PATCH job 状态的旁路。鉴权仿 hub-heartbeat:`Authorization: Bearer <publishable key>` 通道门+`x-hub-id: <device_hubs.id>` 身份锚(组织取 Hub 行、自报组织不采信;事件设备还须属本 Hub)。body 为单条事件对象或 `{events:[...]}`(封顶 100),字段同 device-events(device_id/event_code/device_seq/occurred_at/job_id/payload)。回 200 `{results:[{ok, permanent, persisted, duplicate, throttled, job_status, device_status, kind?, message?}], accepted, rejected}`:ok=已达(duplicate 亦已达);permanent=true 为永久拒绝(Hub 按已处理清行并留痕),permanent=false 保留 outbox 下轮再传

GET/api/wms/wes/automation-pause

人工降级总开关状态(WES 一期批 2-F,2026-11-01,REQ-20261101-16,D83 §6.8 M8):`?warehouse_id=<uuid?>` 查某仓是否处于「暂停自动化编排」(组织级行或该仓行任一暂停即为暂停);不带 warehouse_id 只回组织级行口径。响应 `{paused, scope: org\

GET/api/wms/wes/control-tower

WES 执行控制塔读面(WES 一期批 3-G,2026-11-01,REQ-20261101-16,D83 §6.10 M10/§6.11 M11):query `warehouse_id?`(按仓过滤)、`run?`(演示轮次,§9.2 口径:job payload 的 run_id+任务 source 引用/被该轮 job 挂住)、`layout_id?`(带上才组装 3D 叠加层 viz:设备/工位点、在途 job 路径、人员近似点、热力点)、`heat?`(queue\

POST/api/wms/wes/automation-pause

切换人工降级总开关:body `{warehouse_id?, paused: boolean, reason?}`(warehouse_id 空=组织级全仓)。开启后释放门停推进、设备 job 停下发(消费面查 helper 单点 `isWesAutomationPaused`)、作业回纯人工;每次切换写当前态(`wes_automation_pauses`)+留痕一行(`wes_automation_pause_log`,append-only)。响应同 GET 的状态形。

POST/api/wms/wes/outbox/pump

outbox 泵手动触发(WES 一期批 2-F,D83 §6.7/§6.8 manual caller 口径):按当前登录组织即时泵一轮(桥接新 failed 设备事件+投递到期内部事件,重路由消费者随之即时推进)。常态节拍由 cron `wes-outbox-pump` 每分钟承担,两面共用同一引擎。响应 `{bridged, checked, delivered, failed, retried}`。

POST/api/wms/wes/reroute/scan

工作重路由手动触发(WES 一期批 2-F,D83 §6.8):扫当前组织最近窗口(body `window_minutes`,默认 60、封顶 1440)内报 blocked/fault 的设备,逐台即时处置其在途 job——未开始的改道到同能力声明的其他设备(规则 `wms.wes` 域码 W-E-X1:改道上限默认 3 次、冷却默认 120 秒,超限只报警不循环)、已开始的转人工降级队列并通知仓主管(通知类型 `wms.wes.manual_degradation`/`wms.wes.reroute_exhausted`);人工降级总开关开启时全部转人工。自动面常态时延为分钟级(outbox 泵节拍),本端点供演示与运维即时推进。

POST/api/wms/wes/device-jobs

设备任务下发(WES 一期批 2-E,2026-11-01,D83 §6.6 M6;迁移 768 `wes_device_jobs`):向一台设备下发一条 §8 指令。Body:`warehouse_id*`、`device_id*`、`instruction*`(carry/divert/light_on/light_off/weigh/configure)、`idempotency_key*`(组织内唯一强制非空,同键重发回放既有 job、`replayed=true` 不新建)、锚二选一必填(`task_id` 或 `source_doc_type`+`source_doc_id` 成对,取值 shipment/wave/consolidation_batch/load;无锚/半锚 400 拒绝,DB CHECK 兜底)、`station_id?`、`payload?`、`priority?`、`not_before?`、`hub_id?`。校验:设备属本组织+device_type 已在设备注册表登记(`packages/lib/src/wes/device-registry.ts`)+capabilities 声明合该类型 schema 且能执行该指令,不过 400 人话;设备/任务/工位不存在 404。job_no 走 shared_doc_sequences `wes_device_job`(WJ-)原子取号。成功 `{ job, replayed }`。withWms 宽松默认+组织隔离。

GET/api/wms/wes/device-jobs

设备任务分页列表(批 2-E,D83 §6.6;2026-11-02 控制塔任务明细扩展,D86 §5.6):query `device_id`/`status`/`warehouse_id`/`run_id`(按 job payload 的 run_id 逐字过滤,与控制塔 jobMatchesRun 同口径)/`page`/`page_size`(默认 50、封顶 200),按 created_at 倒序,meta 带 total。响应行=原始 job 行+加法富化字段:`run_id`(payload 提取)、`device_name`、`station_code`/`station_name`(「名 (码)」)、`task_no`/`task_due_at`(锚定 wms_tasks)、`source_no`(wave→wave_no、consolidation_batch→batch_no;shipment/load 暂不解析编号、只回类型)、`sla_bucket`(job 未终态且关联任务处于活跃状态时按 computeSlaRisk 同口径单点 `slaBucketForDueAt` 对任务 due_at 分档,其余为 null)。富化按页批量查(.in 分批 ≤100,禁 N+1)。withWms+组织隔离。AI 注册表已补登 `get_wms_wes_device_jobs`(scenarios=`wes`;WES 其余端点此前未入 agent 注册表,属存量缺口不在本批范围)。

POST/api/wms/wes/device-jobs/claim

设备任务领取(批 2-E,D83 §6.6):Hub 与云端模拟执行方(wes-sim)共用同一端点同一口径。Body:`claimed_by*`(领取方标识)、`device_id?`、`hub_id?`、`limit?`(默认 10、封顶 50)。只领 queued 且 not_before 已到者(priority↓/created_at↑),逐条条件写抢占(status=queued 才置 claimed),被抢走/已取消自动跳过并在 `skipped` 计数。成功 `{ claimed, skipped }`。Hub 侧另有直连 REST 的同形抢占通道(print_jobs 先例形态,device-hub/core/src/cloud.rs WES 段),两通道互不重复领取。

POST/api/wms/wes/device-events

设备事件回流 ingest(批 2-E,D83 §6.6/§8):Body:`device_id*`、`event_code*`(accepted/progress/arrived/completed/failed/state_changed/telemetry)、`device_seq*`(设备侧序号,与 device_id 组成去重键)、`occurred_at*`(设备时钟)、`job_id`(state_changed 外必带)、`payload?`(failed 必带字典内 reason_code)。处理:同序号重复回放不重复驱动(duplicate=true);telemetry 节流落表(同设备 ≥60 秒采样、状态变化即时补记、模拟设备位置流不落表);事件驱动 job 状态迁移(§8 迁移表条件写)+设备资源六态(单点状态机 `resource-state.ts`,非法迁移忽略状态变更、事件留痕);作业级里程碑摘要写任务 step log(字典码映射+幂等键)。成功 `{ persisted, duplicate, throttled, event, job_status, device_status }`。

GET/api/wms/wes/device-events

设备回流事件分页列表(批 2-E):query `device_id`/`job_id`/`page`/`page_size`(默认 50、封顶 200),按 received_at 倒序。加法可选参数(D-3D-DYNAMIC §2.10.2,2026-11-03,缺省行为逐字不变):`run_id`(按 `payload->>run_id` 逐字过滤,与 device-jobs 同写法,供 3D 回放取整轮事件)、`sort=occurred_at`(按设备时钟 occurred_at 正序,回放时间轴口径)。明细留存 90 天(cron `wes-events-retention` 先滚存小时计数再删)。withWms+组织隔离。

GET/api/wms/wes/replay-runs

回放轮次列表(D-3D-DYNAMIC 回放选轮改下拉,2026-11-05):query `warehouse_id`(可选;events 表无 warehouse_id 列,给定时经 `wes_device_jobs` 关联圈定该仓轮次,候选集按 job 新近度封顶 100 个不同轮次)。以 `wes_device_events` 的 `payload->>run_id` 分组聚合本组织有事件记录的轮次(与 GET device-events 的 run_id 过滤同写法、run 提取走 `extractRunId` 单点),每轮回 `run_id`、`first_event_at`/`last_event_at`(occurred_at 首末)、`event_count`,按最近活动倒序、封顶 50 轮,meta 带 total。事件扫描按 occurred_at 倒序分页(页 1000、总封顶 5000 行、id 二级定序防同刻重漏;恰满封顶多探一行确认、不假报);命中封顶时响应带 `truncated=true` 显性标识(不静默截断,此时更早轮次计数为下限);仓库圈定侧的 job 扫描(1000 行)/候选集(100 轮)封顶同样并入 `truncated` 带回。明细留存 90 天,列表只覆盖留存窗。聚合纯逻辑单点 `@docklify/lib/wes/replay-runs`。withWms+组织隔离。AI 注册表已补登 `get_wms_wes_replay_runs`(scenarios=`wes`)。

POST/api/wms/wes/stations/mirror-packing

打包台镜像登记(批 2-E,D83 §6.4 M4;迁移 768 `wes_stations`):Body `packing_station_id*`。把既有打包台在通用工位表登记镜像行(station_type='pack',source_table/source_ref 指回原行)供编排统一寻址;不迁数据、不双写作业状态。重复登记回放既有镜像(replayed=true);打包台不存在 404。

POST/api/wms/wes/devices

云端设备建档(批 3-H,D83 §6.4/§9.2;服务 `wes-registry-admin.ts`):Body `warehouse_id*`、`name*`、`device_type*`(设备注册表已登记)、`adapter_code*`(适配器注册表已注册且 source='cloud';Hub 侧适配器拒云端建档)、`capabilities?`(缺省取适配器声明,须为该类型允许集子集)、`station_id?`、`model?`、`config?`(附加段,adapter_code 由服务端单点写入)。hub_id 由服务端占位 Hub 口径解决(每组织一行 `WES-SIM-CLOUD`,永不配对/心跳,仅作云端建档外键锚,见服务文件头定版);simulated 标牌由适配器 family 派生(只写不读)。幂等:同 (org, warehouse, name) 回放既有行(replayed=true,不改配置);回放命中须比对 device_type+adapter_code,不一致 409 人话(批 3 窄修 P2-2)。成功 `{ device, replayed }`;校验 400 人话、仓/工位不存在 404。withWms 宽松默认+组织隔离。**模拟安全闸(2026-11-04 增补,D114,REQ-20261102-08)**:Body 可带 `sim_gate_token?`——新登记的设备适配器 family='simulator' 且本仓尚未完成启用确认时必填(POST /api/wms/wes/sim-gate 确认后发的一次性令牌,登记时原子消费、消费后回填设备 id);缺失/无效回 409(WMS_STATE_001,details `{sim_gate: 'enable_required'}`);同名回放与已启用仓不重复设闸。

GET/api/wms/wes/sim-gate

模拟运行安全闸·本仓闸状态(2026-11-04,D114,REQ-20261102-08;服务 `wes-sim-gate.ts`):query `warehouse_id*`。响应 `{ warehouse_id, warehouse_name, sim_enabled, enabled_by, enabled_at, impact: { open_orders, open_tasks, real_work_in_progress }, recent_confirmations[] }`——影响面为服务端实时数(未完结订单=wms_shipments 非终态计数、未完结任务=wms_tasks 未完结状态集计数、真实作业=未完结任务中存在非演示种子任务,演示种子按锚定单据 WESRUN- 前缀回查判定);recent_confirmations 封顶 20 条(确认人/时间/闸型/run/当时计数快照,**不含令牌哈希**),ops 查留痕走本端点。仓不存在 404。withWms 宽松默认+组织隔离。

POST/api/wms/wes/sim-gate

模拟运行安全闸·双重确认落审计:Body `warehouse_id*`、`gate_type*`(`enable`=本仓首次启用模拟 / `run`=开启一轮新 run)、`run_id`(run 闸必填,与 job payload.run_id 逐字同口径)、`ack_impact*`(必须 true,第一重勾选)、`warehouse_name_typed*`(第二重:输入仓库名,服务端 trim 后与仓库名逐字复核)。服务端重算影响面并快照进审计行(`wes_sim_gate_confirmations`,append-only,migration 857)。enable 且仓未启用:落行+发一次性令牌(`token` 只在本响应出现一次,sha256 哈希落库,10 分钟有效,绑定 org+仓)——登记首台模拟设备或 POST complete 消费后才算启用完成;仓已启用时幂等回放(replayed=true、无新令牌)。run:审计行本身即凭证(runner 按 org+仓+run_id 查确认行才执行该轮 job),同 run 重复确认幂等回放。成功 `{ confirmation, token?, replayed, sim_enabled }`;ack 未勾/仓名不符/run 缺失 400 人话、仓不存在 404。

POST/api/wms/wes/sim-gate/complete

模拟运行安全闸·存量仓启用完成:Body `warehouse_id*`、`token*`。存量仓(模拟设备在闸上线前已登记、无新设备登记动作)消费 enable 确认令牌落启用完成态,之后模拟器 runner 才放行本仓;仓已启用时幂等成功(already_enabled=true,不必带令牌)。令牌无效/过期/跨仓/已消费回 409 人话。新仓启用不走本端点(第一台设备登记时直接消费令牌)。

GET/api/wms/wes/devices

云端登记设备分页列表(批 3-H):只回 source='cloud' 行(Hub 同步设备走 print-devices 面);query `warehouse_id`/`page`/`page_size`(默认 50、封顶 200),created_at 正序。withWms+组织隔离。

PATCH/api/wms/wes/devices/{id}

云端设备 sim 配置回写(批 3-H,D83 §6.9 故障注入面):Body `{ sim: {...} }` 合并回写 devices.config.sim(演示注入 offline/failure_rate/full_slots、复位清零同面);sim 键须在该设备适配器 capabilitySchema 声明内,未声明 400 拒(不静默吞);Hub 同步设备拒改(配置事实源在 Hub 侧)。**2026-11-03 增补 (c) 手动复位**:Body 可带 `{ reset_blocked: true }`(可单独、可与 sim 同发)——把 blocked 设备人工恢复 idle(现场确认疏通后的人工回报,服务 `wes-device-jobs.ts: resetDeviceBlocked`,经 M6 事件通道写 state_changed(reason=manual_blocked_reset) 留痕、操作人记入该事件 payload 的 actor_user_id(按设备查事件可查);不连带清 sim 配置/格口占用等其他状态;不在 blocked 时幂等成功);Hub 同步设备拒复位(状态以 Hub 上报为准)400 人话、设备不存在 404。成功 `{ device, reset_applied? }`(reset_applied 仅 reset 时回)。withWms+组织隔离。

POST/api/wms/wes/stations

原生 WES 工位建档(批 3-H,D83 §6.4;打包台镜像走 mirror-packing):Body `warehouse_id*`、`code*`、`name*`、`station_type*`(pack/gtp/putwall/induction/sort/weigh/load 注册表校验)、`rated_throughput_per_hour?`、`max_parallel_jobs?`、`accepted_device_types?`。幂等:同 (org, warehouse, code) 回放(replayed=true);回放命中须比对 station_type,不一致 409 人话(批 3 窄修 P2-2)。成功 `{ station, replayed }`;仓库不存在 404。withWms+组织隔离。

GET/api/wms/wes/stations

工位分页列表(批 3-H,含打包台镜像行):query `warehouse_id`/`page`/`page_size`(默认 50、封顶 200)。withWms+组织隔离。

POST/api/wms/wes/layout-links

布局坐标/拓扑关联(批 3-H,D83 §6.4;表 `wes_layout_links`):Body `layout_id*`、`subject_type*`(device/station/flow_line)、`subject_id*`、`x?`/`y?`/`z?`/`heading?`、`topology?`(flow_line 节点/边 jsonb 暂存)。幂等 upsert(同唯一键更新坐标/拓扑,replayed=true;唯一键即 subject 组合、为不可变键,批 3 窄修 P2-2);device/station 须已登记,flow_line 为拓扑虚拟主体不查本体。成功 `{ link, replayed }`;布局/主体不存在 404。withWms+组织隔离。

主数据36 个接口

产品/api/wms/productsGETPOSTPATCHDELETE9 个接口

GET/api/wms/products/{id}/pallet-configs

取某个产品的全部托盘配置(按默认优先、创建时间排序)。

POST/api/wms/products/{id}/pallet-configs

为产品新建托盘配置(name 每产品去重;scene 只能 inbound/outbound/stock;tie/high 必须正整数;uom_code 须是该产品已有 UOM;is_default=true 时清掉同产品其他默认)。

DELETE/api/wms/products/{id}/pallet-configs/{cfgId}

删除某产品的单个托盘配置。

PATCH/api/wms/products/{id}/pallet-configs/{cfgId}

更新托盘配置(可改 retailer/uom_code/tie/high/max_height_in/max_weight_lb/is_default/status;status 只能 active/inactive;uom_code 变更须是该产品已有 UOM;is_default=true 清掉同产品其他默认)。

GET/api/wms/products/{id}/pallet-configs/recommend

按场景+零售商推荐最合适的托盘配置(精确匹配→通用→默认配置),并算出每托盘的 UOM 数量和基础单位数量。

GET/api/wms/products/{id}/uoms

取某产品的全部 UOM(含换算后的体积 volume_cuft / 重量 weight_lb),附产品级默认 UOM 和计费 UOM。

POST/api/wms/products/{id}/uoms

整组替换某产品的 UOM:有 id 按 id 更新、无 id 按 uom_code 匹配更新或新增,不在列表的旧行删除;先整组校验,非法返回 errors;空数组=清空。**行为变更(REQ-20261106-22 批一)**:单位码落库 canonical(大写+别名 EACH→EA);双来源强一致——有 inside 的行按内层链复算必须等于直填 conversion_to_base,不一致拒存;基本单位 conversion_to_base 钉 1;未登记码保存时自动登记进 UOM 字典 wms_uom_codes(本组织自定义行);删除面守卫——新组省略的旧码若被 inside 或单据行引用,整组 400 `UOM_IN_USE` 拒绝(被引用只能停用);保存后产品镜像同步:wms_items.default_uom_code 取默认行规范码、wms_items.uom 恒取 base 行规范码(派生镜像,不随默认翻转)。

DELETE/api/wms/products/{id}/uoms/{uomId}

删除单条 UOM。**行为变更(REQ-20261106-22 批一)**:删除守卫扩至三面——托盘配置引用、被其他 UOM 行 inside 引用、被单据行引用(wms_inbound_receipt_lines/wms_order_lines/wms_outbound_shipment_lines/wms_rma_lines/oms_sales_order_lines/purchase_order_lines 按 item_id 查、wms_transfer_order_lines 按 SKU 查;子表无 organization_id 列按产品定界),任一命中 400 `UOM_IN_USE`(文案指路改用停用);无任何引用才真删。

PATCH/api/wms/products/{id}/uoms/{uomId}

更新单条 UOM(把补丁套到整组做一次校验,非法不落库)。**行为变更(REQ-20261106-22 批一)**:is_default/is_base 均改「先清后设」写序(先清同产品其他行的对应标记再写本行),根治原先写本行撞部分唯一索引必 500;改名(uom_code 规范码变化)先过引用守卫,被 inside/单据行引用时 400 `UOM_IN_USE`;改名与新码同样经字典自动登记;非 base 行 conversion 有库存流水时变更留痕 wms_audit_log;is_active=false 停用永远放行、不经守卫。

物品/api/wms/itemsGETPOSTPATCHDELETE7 个接口

GET/api/wms/items

商品主数据列表:SKU/名称/条码模糊 + 类型/货主/危险品/锂电池/ABC 等级筛选 + 分页;默认只返回启用的。

POST/api/wms/items

新建商品(SKU 在组织+货主维度查重;自动建 EA 默认单位行,UOM 行失败会回滚产品行)

GET/api/wms/items/{id}

产品详情按 id 直查(同表 wms_items+ITEM_COLUMNS、org 限定、含停用产品,未命中 WMS_NOT_FOUND_001;REQ-20261107-23 补——修编辑页拉列表全量被 limit 200 封顶截断、SKU 排名靠后产品误报不存在)

DELETE/api/wms/items/{id}

停用商品(软删:is_active=false,库存台账关联保留)。

PATCH/api/wms/items/{id}

编辑商品主数据(白名单字段;SKU 可改但仍查重;含食品/冷链计重字段)。

POST/api/wms/items/import

商品 CSV 批量导入:浏览器解析成行提交,逐行校验,SKU 重复的行跳过不中断。

GET/api/wms/items/open-lots

批次自动建议:某产品+货主下有可用库存的批次(按最近收货排序)。

零售商/api/wms/retailersGETPOSTPUTPATCHDELETE7 个接口

GET/api/wms/retailers

查询零售商(Retailer)主数据列表(UCC/Packing List 模板关联用),默认只返回启用

POST/api/wms/retailers

新建零售商(code 同组织唯一,重复返回 409)

DELETE/api/wms/retailers/{id}

停用零售商(软删:is_active=false;模板/出库单的 retailer_id 关联保留)。

PATCH/api/wms/retailers/{id}

编辑零售商(白名单字段;code 不可改)。

GET/api/wms/retailers/{id}/templates

Retailer 关联模板展示(REQ-20261028-07):一次返回该 retailer 三个槽位(UCC-Pallet / UCC-Carton / Packing List)的生效模板。解析与打印链共用同一实现(apps/wms/app/api/wms/lib/template-resolve.ts),响应不带 zpl_content(预览走 POST /api/wms/label-templates/render)。权限点 wms.label_templates.view。

GET/api/wms/retailers/{id}/pl-auto

Packing List 自动附带配置读(REQ-20261103-38 / D105):返回 `{ items: [{ client_id, client_name, client_code, auto_print }] }`——本组织全部启用中 clients × 该 retailer 的开关态(未配置行 auto_print=false)。Retailer 编辑页「Packing List 自动附带(按货主)」区消费。

PUT/api/wms/retailers/{id}/pl-auto

Packing List 自动附带配置写(REQ-20261103-38 / D105):body `{ client_id*, auto_print* }`,对 wms_client_retailer_pl_auto 按唯一键 (organization_id, client_id, retailer_id) upsert → `{ client_id, retailer_id, auto_print }`。client 不属本组织回 WMS_NOT_FOUND_001;表未应用时如实 WMS_SERVER_001,不静默假成功。

供应商/api/wms/vendorsGETPOSTPATCHDELETE4 个接口

GET/api/wms/vendors

查询供应商列表(Purchase/WMS 共用),默认只返回启用

POST/api/wms/vendors

新建供应商(code 同组织唯一,重复返回 409)

DELETE/api/wms/vendors/{id}

停用供应商(软删:is_active=false;Purchase/WMS 共用,历史单据保留引用)。

PATCH/api/wms/vendors/{id}

TODO — 待周六 API 审计补充

仓库/api/wms/warehousesGETPOSTPATCHDELETE4 个接口

GET/api/wms/warehouses

查询仓库列表(默认只返回启用的,按 code 排序)

POST/api/wms/warehouses

新建仓库(code 同组织唯一,重复返回 409)

DELETE/api/wms/warehouses/{id}

停用仓库(软删:is_active=false)。

PATCH/api/wms/warehouses/{id}

编辑仓库(白名单字段;code 不可改)。Threshold changes apply to new/updated orders only; existing orders keep their snapshot values.(阈值变更仅对新建/更新的订单生效,已有订单保留快照值,不回溯。)

原因码/api/wms/reason-codesGETPOSTPATCHDELETE5 个接口

GET/api/wms/reason-codes

原因码列表(下拉用;默认只返回启用):category 必填;按 ?lang 或 Accept-Language 返回对应语言的 name(默认 en,缺失回退 en)。

POST/api/wms/reason-codes

新建原因码(Master Data 用):category/code/name_en 必填;同分类下重复 code 返回 400 友好错误。

DELETE/api/wms/reason-codes/{id}

停用原因码(软删:is_active=false,不物理删除,历史单据引用的 code 仍可读;可随时重新启用)。

PATCH/api/wms/reason-codes/{id}

更新原因码(多语言名/启用禁用/排序);空字符串的语言名清为 null(读取时回退 en)。

POST/api/wms/reason-codes/seed

一键导入默认原因码种子(幂等)。body `{ category? }`(不传则全部分类);只补缺失的 (category, code),已有行不覆盖。返回 `{ inserted, skipped }`。权限 `wms.settings.edit`。

计费21 个接口

计费/api/wms/billingGETPOSTPATCHDELETE17 个接口

GET/api/wms/billing/invoices

3PL 对账单/发票列表,带货主名称和每单行数。

GET/api/wms/billing/invoices/{id}

对账单/发票详情:表头(含费率表快照和货主名)+ 计费明细行(含可复算公式)。

PATCH/api/wms/billing/invoices/{id}

账单状态流转(REQ-20261025-14 新增,此前无任何端点能把账单送出 draft):body {status:'sent'

POST/api/wms/billing/invoices/generate

按费率表生成某货主某账期的对账单草稿(draft),自动计价并防重复生成。

GET/api/wms/billing/items

收费项目列表(计费主数据),默认只返回启用项。

POST/api/wms/billing/items

新建一个收费项目(code 在组织内唯一)。

GET/api/wms/billing/rate-sheets

费率表列表,每行带当前是否有效和货主名称。

POST/api/wms/billing/rate-sheets

新建费率表,版本号在同一货主范围内自动递增。

DELETE/api/wms/billing/rate-sheets/{id}

停用费率表(软删);被激活的计费规则引用时禁止删除。

GET/api/wms/billing/rate-sheets/{id}

费率表详情,含明细行(每行带收费项目的 code/name/分类/计价方式/uom)。

PATCH/api/wms/billing/rate-sheets/{id}

编辑费率表基本信息(名称/生效期/备注/启用状态)。

POST/api/wms/billing/rate-sheets/{id}/lines

给费率表加一行明细(绑定收费项目,可覆盖单价和生效期)。

GET/api/wms/billing/rules

Merchant 计费规则列表:每个货主绑哪张费率表,带双方名称和版本。

POST/api/wms/billing/rules

新建 Merchant 计费规则:一个货主一条,把它绑到一张费率表。

DELETE/api/wms/billing/rules/{id}

停用计费规则(软删:is_active=false)。

GET/api/wms/billing/rules/{id}

计费规则详情:settings 原样返回 + 货主和费率表名称。

PATCH/api/wms/billing/rules/{id}

编辑计费规则:整体更新 settings、换绑费率表、启用/停用。

Landed Cost/api/wms/landed-costGETPOSTPATCHDELETE4 个接口

GET/api/wms/landed-cost/hts-overrides

租户级 HTS 税率覆盖列表(按 hts 升序),税率查找优先级高于 USITC 官方同步与内置表。

POST/api/wms/landed-cost/hts-overrides

新增 HTS 税率覆盖(同租户同 HTS 已存在则报重复)。

DELETE/api/wms/landed-cost/hts-overrides/{id}

删除 HTS 税率覆盖。

PATCH/api/wms/landed-cost/hts-overrides/{id}

更新 HTS 税率覆盖:hts / rate / note 至少提供其一。

设置14 个接口

Merchant Users/api/wms/merchant-usersGETPOSTPATCHDELETE6 个接口

GET/api/wms/merchant-users

Merchant(货主)登录账号集中列表:汇总本组织所有商户的 portal_users 去重,附每个用户可访问的商户列表;顶层附调用者是否有 Login-as 权限。

POST/api/wms/merchant-users

新建 Merchant(货主)登录账号并关联到所选商户:邮箱已存在时只做关联不重置密码(返回 linked_existing=true);新邮箱则 Auth 建用户(密码≥8 位)→ 组织成员 → 商户角色 → 关联商户。

DELETE/api/wms/merchant-users/{id}

PATCH /api/wms/merchant-users/[id] — 更新 Merchant 登录账号。

PATCH/api/wms/merchant-users/{id}

更新 Merchant 登录账号:display_name(更新 auth user_metadata)/ client_ids(全量替换该用户可访问的 merchant,增删 portal_users 关联)。

POST/api/wms/merchant-users/{id}/impersonate

POST /api/wms/merchant-users/[id]/impersonate — Login as(发起端)。

POST/api/wms/merchant-users/{id}/reset-password

POST /api/wms/merchant-users/[id]/reset-password — 管理员重置 Merchant 登录账号密码。

Merchant Warehouse Settings/api/wms/merchant-warehouse-settingsGETPOSTPATCHDELETE4 个接口

GET/api/wms/merchant-warehouse-settings

查询 3PL 按货主覆盖的仓库配置列表(null 表示沿用仓库默认)

POST/api/wms/merchant-warehouse-settings

新建或更新货主的仓库覆盖配置(同仓库+货主已存在则更新,upsert 语义)

DELETE/api/wms/merchant-warehouse-settings/{id}

删除货主仓库覆盖配置:该货主回到仓库默认。

PATCH/api/wms/merchant-warehouse-settings/{id}

编辑货主仓库级覆盖配置:自动上架开关三态(null=沿用仓库默认)、GS1 厂商前缀。

Appointment Settings/api/wms/appointment-settingsGETPOSTPUT4 个接口

GET/api/wms/appointment-settings

读取仓库预约(Appointment)配置(承运商改约开关、早到/迟到签到规则、通知邮箱等;表未落地前返回 mock 默认值)

PUT/api/wms/appointment-settings

保存仓库预约(Appointment)配置(部分更新,与旧值合并后存入)

GET/api/wms/appointment-settings/gate-qr

仓库入口二维码状态(REQ-20261025-19 P3,预约设置 Card 5):?warehouse_id= → {active, token(活跃时由登记行重建可重显), expires_at, warehouse_name};仓库须属本组织

POST/api/wms/appointment-settings/gate-qr

仓库入口二维码管理:{warehouse_id, action:'rotate'

通用98 个接口

Vision/api/wms/visionGETPOSTPATCH20 个接口

GET/api/wms/vision/sources

Vision 相机源列表(REQ-20261104-04 / D107 §5.2):本组织 vision_cameras 全量(上限 200、登记时间倒序),逐行富化 hub_name/hub_online(5 分钟心跳口径);同响应带 `hubs`(本组织全部已配对 Hub,登记表单下拉、离线也返回;逐行 `{id, name, platform, last_heartbeat_at, online}`,platform=Hub 所在电脑系统、供同名多台时区分机器,REQ-20261105-48 随 review 裁定 1(a) 补齐)、`warehouses`、`zones`(表单绑定用)。响应 `{sources, hubs, warehouses, zones}`。鉴权 withWms 宽松默认+organization_id 隔离+仓库 assertDataScope

POST/api/wms/vision/sources

Vision 登记相机源:body `{name*, source_type*(nvr_channel/direct_rtsp/usb_hub), hub_id*(三类必填,盒子是唯一分析面), nvr_host/channel_no(nvr_channel 必填), source_ref(direct_rtsp 必过 rtsp 地址校验:rtsp:// 开头、无 userinfo;usb_hub 可空), warehouse_id?, zone_id?, station_id?, point_kind?, stream_sub?, stream_main?, retention_policy?, retention_override_days?, credential_set?}`。**body 出现任何凭证类字段(username/password/credentials 等)直接 400 `WMS_VALID_001` 人话拒绝**——凭证只在现场盒子本机保险库录入、云端只存 credential_set 布尔(D107 §23.3)。dedupe_key 由服务端计算、UNIQUE(organization_id, dedupe_key) 冲突翻人话「已经登记过了」;status 恒 registered(开通走 PATCH)。错误:400 WMS_VALID_001 / 404 WMS_NOT_FOUND_001 / 500 WMS_SERVER_001,均人话

GET/api/wms/vision/sources/{id}

Vision 相机源详情:本组织内单行(富化同列表);不存在/不属本组织 404 `WMS_NOT_FOUND_001

PATCH/api/wms/vision/sources/{id}

Vision 改相机源:可改 `name/warehouse_id/zone_id/station_id/point_kind/stream_sub/stream_main/retention_policy/retention_override_days/credential_set/commissioned/status(registered/active/disabled)`;**身份字段(source_type/hub_id/nvr_host/channel_no/source_ref)不可改**,带了且与现值不同 400 人话「接入身份不能改,要换请停用后重新登记」。**无 DELETE**——停用(status=disabled)代替删除,历史事件与证据引用实体行(D107 §25.1)

GET/api/wms/vision/regions

Vision 区域列表(REQ-20261106-43 / D107 §26.2):query `warehouse_id?/region_type?/status?(active/disabled)/limit?/offset?`,本组织区域按 created_at 倒序、`.range()` 有界分页(默认 100/上限 200)。响应 `{regions}`。逻辑单点 `@docklify/lib/vision/regions`。**Vision 底座未就绪统一信号(W3 窄修 P1-2):910/911 未应用时 Vision 各读口底层表/列不存在类错误统一回 503 `VISION_SETUP_PENDING`(人话「Vision 底座还没启用,请联系管理员完成系统升级后再来」),前端按此码呈现启用提示、不靠错误文本猜测**。鉴权 withWms 宽松默认+organization_id 隔离+warehouse_id 带时 assertDataScope

POST/api/wms/vision/regions

Vision 建区域:body `{name*, region_type*(yard/dock/warehouse/packing/office/worker,查注册表), warehouse_id?, master_kind?(yard_zone/dock/layout_zone/station/free,默认 free), master_id?, notes?}`。绑定口径服务层单点校验:**月台必须绑月台实体、打包台必须绑打包台实体,不建自由月台/自由打包台**;区域类型不认识/已停用 400。错误:400 `WMS_VALID_001` / 500 `WMS_SERVER_001`,均人话。响应 `{region}

GET/api/wms/vision/regions/{id}

Vision 区域详情:本组织内单行;不存在/不属本组织 404 `WMS_NOT_FOUND_001

PATCH/api/wms/vision/regions/{id}

Vision 改区域:可改 `name/notes/status(active/disabled)/warehouse_id/master_kind/master_id`(改绑按合并后形态校验绑定口径);**无 DELETE**——停用代替删除。无可改内容 400 人话;不存在 404 `WMS_NOT_FOUND_001`。响应 `{region}

GET/api/wms/vision/coverage

Vision 覆盖映射列表(REQ-20261106-43 / D107 §26.3):query `camera_id?/target_kind?(region/dock/station/yard_location/gate_lane/layout_zone)/target_id?/at?(ISO 时刻,只回该时刻生效行——按当时覆盖查)/open_only=1/limit?/offset?`,effective_from 倒序。响应 `{coverage}`。逻辑单点 `@docklify/lib/vision/coverage`。鉴权 withWms 宽松默认+organization_id 隔离

POST/api/wms/vision/coverage

Vision 开覆盖行:body `{camera_id*, target_kind*, target_id*, target_label?, role?(primary 默认/secondary), purpose?(panorama/lpr/dot/container_no/trailer_no/seal/general,默认 general——识别管线按用途取流), effective_from?}`。**覆盖变更=开新行**(关旧行走 close 端点),不原地改生效窗;同组织同对象同用途已有生效主视角时唯一索引兜底、400 人话「先把原来那条主视角覆盖关闭再来开新的」;相机不属本组织 404。响应 `{coverage}

POST/api/wms/vision/coverage/{id}/close

Vision 关覆盖行:body `{effective_to?(默认当前时刻)}`——只给该行 effective_to 置值,不删行、不改其他部分;已关行再关 409 `WMS_STATE_001` 人话;不存在 404。响应 `{coverage}

GET/api/wms/vision/subscriptions

Vision 订阅列表(REQ-20261106-43 / D107 §26.2):query `region_id?/warehouse_id?/state?(shadow/active/paused)/limit?/offset?`,updated_at 倒序。响应 `{subscriptions}`。逻辑单点 `@docklify/lib/vision/subscriptions`。鉴权 withWms 宽松默认+organization_id 隔离

POST/api/wms/vision/subscriptions

Vision 订阅 upsert:body `{region_id*, event_type_code*, enabled?, params?, arm_schedule?, state?, shadow_until?}`——(区域×事件类型) 完整行键有则更新、无则新建(**新建强制影子态、shadow_until 写死 +7 天,入参 state/shadow_until 不能跳过影子期**,§13 影子校准期;留痕写失败回 500 `VISION_CHANGELOG_001`——变更已生效、勿重复提交;并发同键冲突 409 人话「该区域已订阅此事件,请直接编辑现有订阅」),每次实际变更写一条留痕、无变更不写。落库前三道校验:适用矩阵(§26.1.1,不适用 400 人话)、安防-only 边界(办公/工人区只许 security/device 类,§26.9)、params 按事件类型 config_schema 校验(未知字段/越界 400 人话)。写操作不盲重试:以完整行键复核收敛同一行。响应 `{subscription, change}`(change 为本次留痕行、无变更时 null)

GET/api/wms/vision/subscriptions/changes

Vision 订阅变更留痕(REQ-20261106-43 / D107 §26.2):query `subscription_id?/limit?/offset?`,created_at 倒序;每条含 `changed_by/change_kind(create/update/enable/disable/state/params/arm_schedule)/diff`(变更字段 `{before, after}`)。留痕只增不改。响应 `{changes}

GET/api/wms/vision/registry/region-types

Vision 区域类型注册表(REQ-20261106-43 / D107 §29.2):平台全局注册表只读口,默认只回启用项,`?all=1` 含停用;每行含 `security_only` 边界标记、`event_pack` 可用事件包(适用关系单一事实源在区域注册侧,事件侧适用集由此派生)。注册项维护走 ops 注册表治理面(§29.6),本口不写。响应 `{region_types}`。鉴权 withWms 宽松默认

GET/api/wms/vision/registry/event-types

Vision 事件类型注册表(REQ-20261106-43 / D107 §29.3):query `region_type?`(带则只回对该区域类型适用的事件,§26.1.1 矩阵过滤)、`all=1`(含停用)。每行含 `config_schema`(配置面按 schema 自动渲染)/`applicable_region_types/detector_pack_ref/wave/default_severity/evidence_required/task_convertible/metrics_pack`(后四者 911 补列)。**`applicable_region_types` 为服务端派生字段(源在区域注册侧 `vision_region_types.event_pack`、按区域侧成员关系反查计算,911 起事件侧无此落列、无独立写路径)**。注册项维护走 ops 治理面,本口只读。响应 `{event_types}

GET/api/wms/vision/index

Vision 统一关联索引读口(REQ-20261106-43 / D107 §26.4):query `entity_kind*&entity_id*&from*&to*`(ISO 时间窗)。按当时覆盖映射取相机集:响应 `{index{entity_kind, entity_id, from, to, coverage(full/partial/none 三态), gaps[](no_coverage/no_primary_view/partial_time_coverage 缺口键), cameras[](逐台 role/purpose/quality——primary=exact 精确关联、secondary=time_window 时段关联), pack_windows[](实体为打包台或绑打包台的区域时按 station+时间窗取 PackVision 窗口,含 locked 证据锁定标注), evidence_lock_count}}`。只做派生查询、**不新建片段存储**;无覆盖回 coverage='none' 是正常结果不报错。逻辑单点 `@docklify/lib/vision/index-read`。错误:400 `WMS_VALID_001`(缺参/时间窗非法,人话)/ 500 `WMS_SERVER_001`。鉴权 withWms 宽松默认+organization_id 隔离。本端点不新增 AI/agent 工具登记(读口按 §31.7 实现期评估,先行登记于此)

GET/api/wms/vision/evidence-locks

Vision 证据锁定列表(REQ-20261106-43 / D107 §26.4):query `status?(locked/released/expired)/entity_id?/source_kind?/source_ref?/limit?/offset?`,created_at 倒序。响应 `{evidence_locks}`。逻辑单点 `@docklify/lib/vision/evidence`。鉴权 withWms 宽松默认+organization_id 隔离

POST/api/wms/vision/evidence-locks

Vision 建证据锁定:body `{source_kind*(event/packvision_window/segment), source_ref*(事件号/窗口号/片段标识), entity_kind?, entity_id?, reason*(必填,W3 窄修 P2-2:空/缺失 400 `WMS_VALID_001`,route 与 lib 双侧校验), retain_until?}`。锁定是保全动作——只固化被引用片段、不扩围整段录像;片段实际固化/导出走 §9 通道与导出批,本口只落锁定记录事实源(含谁/何时/因何引用留痕)。响应 `{evidence_lock}`。错误:400 `WMS_VALID_001` / 500 `WMS_SERVER_001`,均人话

POST/api/wms/vision/evidence-locks/{id}/release

Vision 释放证据锁定:status locked→released(片段回 §12 留存分档)、不删行(释放本身留痕);已释放/已到期再释放 409 `WMS_STATE_001` 人话;不存在 404。**关闭告警不自动解锁**(§26.7),解锁只能走本口。响应 `{evidence_lock}

Slotting/api/wms/slottingGETPOST10 个接口

POST/api/wms/slotting/run

跑一次 Slotting 分析(分析页「重新分析」按钮;夜间 cron 同一 `runSlottingBatch`)。算 velocity(近 period_days 天拣选件数,`wms_tasks` pick + `wms_order_lines`)+ distance tier,写 `wms_slotting_scores`;ABC 由跑批按本仓本轮 velocity 自算(与平台 ABC 分析同一纯函数 `classifyAbc`:累计出件占比 <80% → A、<95% → B、其余 → C、零出件 C,2026-11-04 修复线口径,不读 `wms_items.abc_class`);算 affinity(90 天出库单同单共现、只算 A/B 类、订单抽样上限 5000)写 `wms_slotting_affinity`;记 `wms_slotting_runs` 并回填 `wms_warehouses.slotting_last_run_at`。写路径用 service role(新表未启 RLS,仿 forecast/run),鉴权 `withWms` + `assertDataScope` 在入口完成。定时跑批:每日 04:00 PDT cron 任务键 `wms-slotting`(`/api/cron/run?task=wms-slotting`),只跑 `slotting_enabled` 且距上次跑批 ≥ `slotting_interval_days` 的仓库。

GET/api/wms/slotting/scores

Slotting 打分列表:读 `wms_slotting_scores` 缓存(不现场算),附 SKU/产品名/当前库位 code/zone。`run_id` 缺省取该仓最新一次跑批;无跑批时回空列表(`run_id=null`)。标准列表信封(修复线口径):`data` = 行数组、`meta = {total, page, page_size, run_id}`。

GET/api/wms/slotting/affinity

Slotting 关联对列表:读 `wms_slotting_affinity` 缓存,按共现率倒序,附两端 SKU/产品名/库位 code。`run_id` 缺省最新一次跑批。信封同 scores(`data` 行数组 + `meta{total,page,page_size,run_id}`)。

POST/api/wms/slotting/recommendations

每个 SKU 推荐 3 个候选目标库位(设计 §4.1):同仓 `location_type='pick'` 的空库位(无库存)→ distance tier near 优先排序 → 调 `suggestPutaway` 做合规过滤(temp_zone/过敏原/location group 禁区),排除已占用库位。单产品失败不影响整批(行内 `error` 回报)。

POST/api/wms/slotting/apply

按用户选定的候选库位批量生成移库任务:逐条调既有 `createMoveTask`(`wms_move_tasks` 表与执行流程零改动),`reason_code='slotting_optimize'`;逐条成败分开回报,单条失败不回滚整批。

GET/api/wms/slotting/scores

Slotting 打分列表:读 `wms_slotting_scores` 缓存(不现场算),附 SKU/产品名/当前库位 code/zone。`run_id` 缺省取该仓最新一次跑批;无跑批时回空列表(`run_id=null`)。标准列表信封(修复线口径):`data` = 行数组、`meta = {total, page, page_size, run_id}`。

GET/api/wms/slotting/affinity

Slotting 关联对列表:读 `wms_slotting_affinity` 缓存,按共现率倒序,附两端 SKU/产品名/库位 code。`run_id` 缺省最新一次跑批。信封同 scores(`data` 行数组 + `meta{total,page,page_size,run_id}`)。

POST/api/wms/slotting/run

跑一次 Slotting 分析(分析页「重新分析」按钮;夜间 cron 同一 `runSlottingBatch`)。算 velocity(近 period_days 天拣选件数,`wms_tasks` pick + `wms_order_lines`)+ distance tier,写 `wms_slotting_scores`;ABC 由跑批按本仓本轮 velocity 自算(与平台 ABC 分析同一纯函数 `classifyAbc`:累计出件占比 <80% → A、<95% → B、其余 → C、零出件 C,2026-11-04 修复线口径,不读 `wms_items.abc_class`);算 affinity(90 天出库单同单共现、只算 A/B 类、订单抽样上限 5000)写 `wms_slotting_affinity`;记 `wms_slotting_runs` 并回填 `wms_warehouses.slotting_last_run_at`。写路径用 service role(新表未启 RLS,仿 forecast/run),鉴权 `withWms` + `assertDataScope` 在入口完成。定时跑批:每日 04:00 PDT cron 任务键 `wms-slotting`(`/api/cron/run?task=wms-slotting`),只跑 `slotting_enabled` 且距上次跑批 ≥ `slotting_interval_days` 的仓库。

POST/api/wms/slotting/recommendations

每个 SKU 推荐 3 个候选目标库位(设计 §4.1):同仓 `location_type='pick'` 的空库位(无库存)→ distance tier near 优先排序 → 调 `suggestPutaway` 做合规过滤(temp_zone/过敏原/location group 禁区),排除已占用库位。单产品失败不影响整批(行内 `error` 回报)。

POST/api/wms/slotting/apply

按用户选定的候选库位批量生成移库任务:逐条调既有 `createMoveTask`(`wms_move_tasks` 表与执行流程零改动),`reason_code='slotting_optimize'`;逐条成败分开回报,单条失败不回滚整批。

Adjust Reasons/api/wms/adjust-reasonsGETPOSTPUTDELETE4 个接口

GET/api/wms/adjust-reasons

查询库存调整原因代码列表(主数据,下拉框用),默认只返回启用的,按排序号排列

POST/api/wms/adjust-reasons

新建一条库存调整原因代码(code 会转小写+下划线规范化,重复返回 400)

DELETE/api/wms/adjust-reasons/{id}

删除一条库存调整原因代码(硬删)。

PUT/api/wms/adjust-reasons/{id}

更新库存调整原因代码的三语名称、是否启用和排序。

Condition Codes/api/wms/condition-codesGETPOSTPUTDELETE4 个接口

GET/api/wms/condition-codes

查询货物状况(Condition)代码列表(对应 goods_type,主数据下拉用),默认只返回启用的

POST/api/wms/condition-codes

新建一条货物状况(Condition)代码(code 转小写+下划线规范化,重复返回 400)

DELETE/api/wms/condition-codes/{id}

删除一条商品状况代码(硬删)。

PUT/api/wms/condition-codes/{id}

更新商品状况代码的三语名称、是否启用和排序。

Doc Charges/api/wms/doc-chargesGETPOSTPATCHDELETE4 个接口

GET/api/wms/doc-charges

附加费列表(2026-10-19 新增,migration 479;出库单/入库单详情的 Accessorial Charges tab)。查询参数 `entity_type*`(`wms_shipment` 出库单 / `wms_inbound_receipt` 入库单)、`entity_id*`(单据 UUID)。返回该单据全部 charges,每行带六语 `billing_item`(code/name/unit)+ 服务端解析的显示名 `item_name`(目录英文基准名)/ `item_code`(目录 code,目录行缺失时回落行上快照 code)+ `sync_status`(`not_synced` 未同步 / `synced` 已同步 / `invoiced` 已开票)+ `billed_doc_id`(开票单据 id:AR=发票 id / AP=账单 id,未开票为 null)。开票事实以 `billing_events` 为单一事实源、由服务端按 `billing_event_id` 实时派生(REQ-20261024-06 定案);行上 `invoice_id` 列从未回填、已降预留,不作判定依据。权限:`wms.outbound.view` 或 `wms.inbound.view`(任一)。示例:`GET /api/wms/doc-charges?entity_type=wms_shipment&entity_id=<uuid>` → `{ok:true,data:[{id, entity_type, entity_id, billing_item_id, billing_item_code:"WMS-RUSH-FEE", item_name:"Rush Fee", item_code:"WMS-RUSH-FEE", quantity:1, unit:"order", unit_price:50, amount:50, currency:"USD", status:"active", sync_status:"synced", billing_event_id, synced_at, billed_doc_id:null, billing_item:{code,name_en,name_zh,...}}]}`。

POST/api/wms/doc-charges

新建附加费(2026-10-19 新增,migration 479)。Body:`entity_type*`(`wms_shipment`/`wms_inbound_receipt`)、`entity_id*`(单据 UUID)、`billing_item_id?`(Accounting 收费目录 `billing_items` UUID,module=wms + category=accessorial;传了即走自动同步)、`quantity?`(默认1)、`unit_price?`(默认0)、`currency?`(默认USD)、`description?`。`amount`=round2(qty×price) 自动算。不传 `billing_item_id` 时为自由项(`billing_item_code` 手填),**不同步**到 Accounting。新建后对有目录条目的行自动 `syncDocCharge`(fire-and-forget,失败记 `warnings[]` 不阻塞建行)。同步路径:charge → `billing_events`(idempotency=once, eventType=`accessorial_outbound`/`accessorial_inbound`)→ 月结 cron → AR 发票(出库单,按货主)/ AP 账单(入库单,按 vendor,migration 483)。**closed 状态门**(2026-10-24,REQ-20261024-05):归属单据已 `closed` 时拒绝新建 → `WMS_VALID_001` + `details.reason="order_closed"`(文案 MSG_CHARGE_ORDER_CLOSED,message-standards 登记;closed 为入库单真实终态,出库单枚举暂无此值、同查不触发)。权限:按 entity 分发 `wms.outbound.edit`(出库单)/ `wms.inbound.edit`(入库单)。

PATCH/api/wms/doc-charges/{id}

修改附加费(2026-10-19 新增)。Body:`quantity?`/`unit_price?`/`description?`(只改这三项,改后重算 amount)。只有 `status='active'` 且**尚未同步**(`billing_event_id` 为空)的行可改;已同步行改价 → 400 英文大白话(引导移除后新建);已作废行 → 400。**closed 状态门**(2026-10-24,REQ-20261024-05,与 POST/DELETE 同口径):归属单据已 `closed` → 400 `WMS_VALID_001` + `details.reason="order_closed"`。并发更新用 `status=active AND billing_event_id IS NULL` 条件写防竞态。权限:按 entity 的 `wms.outbound.edit` / `wms.inbound.edit`。

DELETE/api/wms/doc-charges/{id}

移除附加费(2026-10-19 新增;**2026-10-23 定版改真移除语义**,覆盖原「置 void 作废」口径)。按行状态分档:存量 `status='void'` 行 → 幂等返回当前行(不重复处理);归属单据已 `closed` → 400 `WMS_VALID_001` + `details.reason="order_closed"`;已开票(行上 `invoice_id` 或关联 `billing_events` 已 invoiced/已挂 invoice_id/bill_id,开票事实以 event 侧为准)→ 400 + `details.reason="already_invoiced"`,引导去账单侧走贷项/调整;已同步未开票 → 先条件删除关联 billing event(`invoiced=false` 守卫防月结并发认领)再删 charge 行;未同步 → 直接删 charge 行。删除前写 `wms_audit_log`(action=`wms.doc_charge.remove`)留痕。权限:按 entity 的 `wms.outbound.edit` / `wms.inbound.edit`。

Print Devices/api/wms/print-devicesGETPOSTPATCHDELETE4 个接口

GET/api/wms/print-devices

查询打印设备列表(打印中心用),附设备所属 Hub 和仓库名称

POST/api/wms/print-devices

设/清「我的默认打印机」(D33):body { warehouse_id*, kind?, device_id(uuid 设默认 / null 清除)},写 user_printer_defaults(迁移 597),作用域焊死为当前用户自己;device_id 须属本组织

PATCH/api/wms/print-devices

打印设置维护(2026-10-23 定版:后台是打印配置的事实源):给设备补挂/改挂仓库、改打印机类型、设/取消仓库默认(标签/文档各一台)。设默认时先清同 (org, 仓库, 类型) 其他设备的默认标记(DB 部分唯一索引兜底);带着默认标记改挂到已有同类默认的仓库会提前大白话拦截并点名既有默认(打印 review P2-1),漏网的 23505 也有可读文案兜底;改类型与既有默认标记冲突时顺带清掉那侧默认。

DELETE/api/wms/print-devices?id=

删除一台打印设备的云端记录(Hub 本地仍在时下次同步会重新登记,属预期)

承运商/api/wms/carriersGETPOST3 个接口

GET/api/wms/carriers

查承运商主数据(shared_carriers)下拉列表,只返回启用(is_active=true)的。

POST/api/wms/carriers

页内快建承运商(YMS Entry 一期 §4.2):最小 body 只需 name;同组织同名已存在时直接返回既有行(防重复建)。

GET/api/wms/carriers/{id}/services

某承运商的服务列表(只返回启用项);若无服务行则回退用承运商的 shipping_methods 数组。

Labor/api/wms/laborGETPUT3 个接口

GET/api/wms/labor/performance

人员绩效统计:完成任务数、平均任务耗时、总工时(全部从任务表和工时表聚合)。

GET/api/wms/labor/skills

People Ops 技能矩阵查询:员工 + 工作技能(操作×货主)+ 数据范围(自己+下属链,链顶看全仓);已离职不返回。

PUT/api/wms/labor/skills

People Ops Skills API(WMS → Settings → People Ops Skills)

Outbound Shipments/api/wms/outbound-shipmentsGETPOST3 个接口

GET/api/wms/outbound-shipments

发运单 Shipment 列表(shipment 只能由系统自动产生,SP- 前缀;不可手工创建);支持单号/运单号/Pro#/BOL# 多字段模糊、状态/订单类型/日期范围筛选;附带关联的出库单号和 Load 号。

GET/api/wms/outbound-shipments/{id}

发运单详情:shipment 全字段 + 明细行(含产品 SKU/名称)+ 关联出库单号 + Load 号。

POST/api/wms/outbound-shipments/{id}/deliver

发运单确认送达(仅 shipped → delivered)

Transfer Orders/api/wms/transfer-ordersGETPOSTPATCH3 个接口

GET/api/wms/transfer-orders

调拨单列表(入仓控制塔数据源):支持状态/平台/货主筛选,分页。

POST/api/wms/transfer-orders

创建调拨单(P0 只建内部单,不调平台入仓计划 API):单号经 shared_doc_sequences 原子取号(TO-000001);dest_location_id 不传时自动取该平台首个可用位置;行写失败自动回滚主单。

PATCH/api/wms/transfer-orders/{id}

更新调拨单:状态机校验(draft→planned→in_transit→delivered→receiving→closed;任意→cancelled/exception);数量字段非负整数。

Work Centers/api/wms/work-centersGETPOSTPATCH3 个接口

GET/api/wms/work-centers

查询工作中心列表(只返回启用的,按编码排序,最多 200 条)

POST/api/wms/work-centers

新建工作中心(编码重复返回 409)

PATCH/api/wms/work-centers/{id}

更新工作中心(真拣选一期新增):绑定/解绑默认组装暂存位(start-picking 解析链第二级),可同时改 name/capacity_per_hour/is_active。staging_location_id 必须为 staging 类型库位,传 null 解绑。

Battery Incidents/api/wms/battery-incidentsGETPOST2 个接口

GET/api/wms/battery-incidents

锂电池破损隔离记录列表(按 created_at 倒序,限 100 条),联查产品 SKU/名称/UN 编号和库位码;支持状态/产品/仓库筛选。

POST/api/wms/battery-incidents

上报锂电池破损/异常并冻结库存:校验产品为锂电池(非锂电池拒绝),插入隔离记录(status=handling 走任务流 / open 仅冻结),对应库存 detail 行冻结为 hold。

Carrier Accounts/api/wms/carrier-accountsGETPOST2 个接口

GET/api/wms/carrier-accounts

查询承运商账号列表(发货台选账号、日终 Manifest 用),默认只返回启用的(数据源已统一为 Master Data 承运商账号 shared_carrier_accounts,REQ-20261027-17)

POST/api/wms/carrier-accounts

新建承运商账号(warehouse_id 与 client_id 至少传一个;EOD 日终交接单的前置)

Hazmat Config/api/wms/hazmat-configGETPUT2 个接口

GET/api/wms/hazmat-config

读锂电池/危险品仓库配置;warehouse_id 不传=读组织级默认;无行或配置表未建时返回默认(handling_level=standard)。

PUT/api/wms/hazmat-config

保存锂电池/危险品仓库配置(按 organization_id+warehouse_id 唯一键 upsert;6 个开关全必填)。

Inbound/api/wms/inboundGETPOST2 个接口

GET/api/wms/inbound/receive-tasks

收货任务列表,可按入库单或状态过滤。

POST/api/wms/inbound/receive-tasks

批量建收货任务:每个入库单独立建一个任务(已建未完成的不重复建)。

Merchant Strategies/api/wms/merchant-strategiesGETPOST2 个接口

GET/api/wms/merchant-strategies

查询货主的策略配置(上架/分配策略),返回已配置项 + 每个策略的生效值及来源(仓库级/货主级/系统默认)。2026-10-22 起:不传 client_id 为 list 模式,返回本组织全部已配置行 + 策略选项(无 effective),供 Task Rules「客户例外策略」段一次拉全

POST/api/wms/merchant-strategies

新建或更新货主策略配置(上架策略/分配策略;按货主+仓库+策略键 upsert,已存在则更新)。2026-10-22 复审补强:client_id / warehouse_id 必须属于本组织,否则 WMS_VALID_001

Merchants/api/wms/merchantsGETPOST2 个接口

GET/api/wms/merchants

WMS 内商户(货主)下拉列表(本组织启用的商户,code/name 模糊搜索,最多 200 条)

POST/api/wms/merchants/{id}/abc-run

POST /api/wms/merchants/[id]/abc-run — 手动触发单个 merchant 的 ABC 计算

Putaway Tasks/api/wms/putaway-tasksGETPOST2 个接口

GET/api/wms/putaway-tasks/{id}

上架任务详情:任务头+上架明细行(托盘 LPN/商品 sku+name/起止库位编码均已丰富)。

POST/api/wms/putaway-tasks/quick

手机临场上架 Quick Put Away:phase=scan_done 扫托盘先建 in_progress 任务记托盘信息,phase=complete 选库位提交(支持 resume_task_id 断点续做);client_step_key 幂等防重复提交。

Putaway/api/wms/putawayPOST2 个接口

POST/api/wms/putaway/confirm

上架确认:storage 位扫托盘 LPN+库位写双腿台账托盘落位;picking 位扫库位+输数量记入虚拟托盘。pallet 模式的商品解析(REQ-20261027-01):托盘头 item_id 为空且未传 task_line_id 时,回退查托盘明细(wms_pallet_lines)——明细恰好 1 个产品按单品托继续(托头数量为空时数量取明细合计;托头有值时数量口径不变,仍为 task_line_qty ?? 托头 qty);明细 0 行报「这托托盘上没有产品明细,无法上架,请先检查托盘」;明细 ≥2 个产品(真混托)报「这托上有多种产品,不能整托一起上架,请按产品分别上架」。经 task_line_id 上架时仍以任务行 item_id/qty 为准。**整托拆托(REQ-20261027-25)**:目标为 picking 位且 body 带 pallet_id、未带齐 item_id/qty 时,不再报缺字段——按托盘实际内容推导:明细按 (item_id, lot_no, expiry_date) 分组(无明细回退托头 item_id+qty),逐组写源位负腿(物理托)+目标位正腿(虚拟托)并同步 lot/库存明细,托头清零落位目标位;多个不同产品整单拒绝(pick 位一格一品,请按产品分别上架走逐行模式);空托(含重复确认)拒绝不双记。带齐 item_id+qty 时逐行模式口径不变(pallet_id 被忽略)。**任务归属与归行(REQ-20261104-47 加法)**:Body 带 task_id 且该任务有绑定行时,pallet_id 不在绑定集内回 PALLET_NOT_IN_TASK 硬拒(不带 task_id 或任务无绑定行则不校验,自由上架不变);未带 task_line_id 时按 pallet_id 反查——全局恰好 1 条 pending 上架行且任务未完结、且行 qty 与托头 qty 一致(托头 qty 为空以行 qty 为准)时自动归行(行置 done+步骤日志+整托拆托模式同口径);整托(storage 位)落位后,该托在原库位的 wms_inventory_lot 行与 wms_inventory_detail 镜像行原地迁到目标位(只改 location_id,行数与数量不变;单行失败只记日志不挡主流程)。注记(REQ-20261104-47 review P2-6):`PALLET_NOT_IN_TASK` 正文为通用提示(六语消息表为静态串、无占位符插值),点名信息在 error.details(task_no+pallet_id);手机 Web/原生执行端以自有文案点名扫到的码与本任务应有托盘。**错误文案**:本端点自产的校验/状态错误(缺库位、库位停用、缺产品数量、数量非正、混托、空托、托盘已发运、跨仓、任务行已处理等)为六语言大白话文案,按 `?lang=`/`x-lang`/`Accept-Language` 解析(默认 en),错误码仍为 WMS_VALID_001/WMS_STATE_001/WMS_SERVER_001,details 结构不变。

POST/api/wms/putaway/suggest

按上架规则引擎+货主策略返回排序后的建议库位;传 pallet_lpn 走快捷模式(后台从托盘解析商品/数量/货主,只需传仓库+托盘)。

Packing Stations/api/wms/packing-stationsGETPOST2 个接口

GET/api/wms/packing-stations

打包站与打包日志查询(REQ-20261025-27 合并端点,query `action` 分发)。合并理由:saas 路由贴 Vercel 2048 上限,站 CRUD+日志+逐包重打只占一个路由文件;域拆分落地后可再拆细。权限 `wms.packing.view` + assertDataScope(按站属仓/客户范围收窄)。

POST/api/wms/packing-stations

打包站写操作(同上合并端点,body `action` 分发):站 CRUD / 活动日志批量写 / 订单详情逐包重打面单。日志表 `wms_packing_logs` 为 append-only(触发器禁 UPDATE/DELETE),warehouse 与 user 由服务端按站主数据与登录上下文盖章,不信客户端自报。

Temperature Readings/api/wms/temperature-readingsGETPOST2 个接口

GET/api/wms/temperature-readings

按温区+日期查当日温控读数(CMP-05 超温样本核对、移动端录入面回显)。date 按 UTC 日切分,缺省今天;仅返回当前组织数据(withWms 组织隔离)。

POST/api/wms/temperature-readings

温控读数人工录入(报表 P3 批 B1 / CMP-05 一期,D81 §3.4):巡检员在移动端录入面提交一条温度读数,落 wms_temperature_readings(source='manual'、created_by=当前用户)。权限隔离:登录+本组织成员(withWms),仓库/温区均按当前组织校验归属,跨组织 id 按「找不到」处理。写入幂等:唯一键六元组 (organization_id, warehouse_id, zone_code, recorded_at, temperature_c, source) 已有行时不重复落行,回既有行且 meta 带 duplicated=true(meta.created=false)。

Driver Verification/api/wms/driver-verificationGETPUT2 个接口

GET/api/wms/driver-verification/policy

GET /api/wms/driver-verification/policy — 设施司机核验策略(与 Yardor 面同一行、同一底座服务、同一审计轨);参数 warehouse_id(本组织仓库)

PUT/api/wms/driver-verification/policy

PUT /api/wms/driver-verification/policy — 写设施司机核验策略全量对象 {warehouse_id*, strength, default_tier, deadline_minutes, scope(scope_mode+scope_carriers), accept_external, require_per_visit, gate_otp_enabled, deadline_strict, optional_docs};服务层写审计行

Battery Alerts/api/wms/battery-alertsGET1 个接口

GET/api/wms/battery-alerts

锂电池三类预警查询(专区温度无遥测 / 新的破损隔离记录 / 库龄超 180 天抽检);本组织无锂电池产品时返回空列表。

Template Variables/api/wms/template-variablesGET1 个接口

GET/api/wms/template-variables

模板变量目录(REQ-20261102-52,D93 §4.4.4):静态系统变量+本组织扩展字段定义(头级 wms_outbound_order/行级 wms_outbound_order_line)在服务端合并返回,条目带 source 分组标记(system/extension)与 parent 层级;B2 加法:条目新增显式 level 字段(doc/line)供编辑器分组、前端不靠 parent 猜;?kind=&media= 按适用面过滤,停用定义与 gap 条目不进目录;组织取登录态、不接受自报;REQ-20261104-06 起条目加法带 scope(变量级别:order/shipment/item/carton_pallet)与 hint(六语一句话说明:打印什么+值从哪来)

Lpn/api/wms/lpnPOST1 个接口

POST/api/wms/lpn/batch-print

LPN 预打印(桌面端):批量生成空白 LPN 并预建托盘行(status=preprint,未绑定库位),供工人揣身上、移库时现场贴+扫码绑定。

Forecast/api/wms/forecastGET1 个接口

GET/api/wms/forecast/labor

人力需求预测(读 wms_forecasts 跑批缓存):warehouse_id 必填、days≤30;meta.params 含 uph_pick/putaway/pack 与 labor_sources(JSON:逐工种口径来源——standard 带标准版本 effective_from/标准分钟/难度/uom、uph 带引擎 UPH;批三-B REQ-20261108-13 起已立标准的类型按标准工时=预测量×标准分钟×难度算需求工时,未立标准保留 UPH 路径)

Zone Picking/api/wms/zone-pickingGET1 个接口

GET/api/wms/zone-picking/performance

Zone Picking 绩效看板(只读聚合):按 picker×zone 统计任务数/完成数/完成率/拣选件数/平均用时/超时数与超时率,附 zone 均值。参数:`days`(默认 30、上限 365)、`warehouse_id`(可选,不传=全组织)。响应 `zones` 数组(2026-11-04,REQ-20261104-08 加法扩展):按 zone 整组聚合+`picker_count`(窗口内该 zone 有任务的指派人数,不含未指派)+`units_per_hour`(每小时拣选件数,只按有计时记录的已完成任务计:其件数÷其总用时;无计时记录为 null),供绩效页各 Zone 效率柱状图。鉴权:组织成员(withWms)。

Supervisor Approvers/api/wms/supervisor-approversGET1 个接口

GET/api/wms/supervisor-approvers

主管放行批准人名单(手机端拣选放行选人用)。只列有资格批准的人:组织管理员/所有者(platform_roles.role_type ∈ owner/admin),或在职员工档案岗位为主管级(shared_job_titles.is_supervisor_level=true)的人;排除请求人本人(批准人 ≠ 操作人)。资格口径与 pick 接口的 supervisor_override 服务端强校验同源(lib/supervisor-approval.ts)。

Carts/api/wms/cartsPOST1 个接口

POST/api/wms/carts/{id}/checkin-consolidation

汇集区**停车位登记册**维护(REQ-20261103-40,Andy 2026-11-03 定版;migration 827 表 wms_consolidation_parking_spots)。停车位是轻量登记册、**不是 location**:无库存/容量/占用排他语义,合单/打包等业务逻辑永不读;只给人找车+等时提醒。编号 P- 前缀、服务端按汇集区顺号生成(P-01 起、取现有最大号+1,唯一约束兜底并发撞号),**不许用户自编**。占用不落列:由未关闭签到推导(车 at_consolidation 且其最近 checkin movement 挂该车位)。维护面落 Consolidation Slots 页「停车位」分区,与格口池同权限面(withWms+org 隔离+assertDataScope)。前置:migration 811 已应用。

Receiving Tasks/api/wms/receiving-tasksPOST1 个接口

POST/api/wms/receiving-tasks

为入库单创建入库任务(task_type=receive,按收货行生成任务明细并回写入库单锁定桌面直接收货;同单已有未完成任务时幂等返回)

Device Hubs/api/wms/device-hubsGET1 个接口

GET/api/wms/device-hubs

Device Hub 名册(2026-11-04 新增,D115 / REQ-20261104-48):当前组织全部 Hub(上限 200),逐个回 `{id, name, display_name(命名线 REQ-20261104-44 的列、未就位时回 null), hub_version, platform, warehouse_id, last_heartbeat_at, online(5 分钟口径与 stations/status 一致), devices{printer, scale, other}(devices 台账按类型聚合), cameras(pack_cameras 绑定数)}`。顶栏「这台电脑上的 Hub」状态面单一数据源:网页本机 WS 探测拿到 cloud_hub_id 后在本名册内解析绑定与心跳。只读、组织隔离(withWms 宽松默认);**调用方须带 x-organization-id 头**(withWms 组织校验,缺失回 WMS_VALID_001/400——顶栏弹层曾漏带致名册恒加载失败、弹层恒呈待确认,REQ-20261107-29)

Pack Exceptions/api/wms/pack-exceptionsGET1 个接口

GET/api/wms/pack-exceptions

跨单打包异常队列(D58 唯一净增路由):query `warehouse_id?/client_id?/type?/status?/resolution?/page/page_size`,`.range()` 分页+meta.total;响应另带 `weight_attempts_today{pass,blocked,overridden,not_checkable}` 当日称重四数(站台班次视图口径)。EOD 页以 `status=pending_verify` 取本仓未决报缺计数;manifest 首次交接服务端同口径拦截(Q4)。

Task Monitor/api/wms/task-monitorGET1 个接口

GET/api/wms/task-monitor/summary

任务监控聚合:KPI(含环比)/按状态·类型分布/近 N 天趋势(含按天×类型)/按时完成率/按人统计/实时任务。

Temperature Import/api/wms/temperature-importPOST1 个接口

POST/api/wms/temperature-import

温控读数 CSV 批量导入(报表 P3 批 B1 / CMP-05 一期):整批校验后一次落库,失败行不落、逐行回人话原因。落 wms_temperature_readings(source='import'、source_ref=批次号、created_by=当前用户)。权限隔离:登录+本组织成员(withWms),仓/区只在当前组织内解析。写入幂等:单批先按六元组 (organization_id, warehouse_id, zone_code, recorded_at, temperature_c, source) 批内去重、再 upsert ignore-duplicates 落库;inserted 只计真落行,被跳过的重复行计入回执 duplicates(同文件重导 inserted=0、duplicates=全部有效行)。

Tenant Profile/api/wms/tenant-profileGET1 个接口

GET/api/wms/tenant-profile

查轻量租户档案(只返回 industry_profile),供 WMS 页面判定是否显示重量字段组;登录+组织归属即可(WMS 操作员可用)。

Waves/api/wms/wavesGET1 个接口

GET/api/wms/waves/{id}

波次详情:波次主行+关联出库单(含状态)+关联拣选任务(含状态)+拣选/打包进度统计。

OMS · 订单管理

订单52 个接口

订单/api/oms/ordersGETPOSTPUTPATCHDELETE47 个接口

GET/api/oms/orders

销售订单列表。支持 status(单)/ statuses(逗号分隔多选)/ exclude_statuses(逗号分隔排除,可选、增量)/ channel_id / client_id / created_from~created_to / created_to_exclusive(排他上界,可选、增量)/ q(订单号/渠道订单号/客户名模糊)/ has_shortage(只返回有缺货行的订单)筛选;返回 items + total。

POST/api/oms/orders

创建草稿销售订单(含订单行),order_no 自动生成(SO-YYYYMMDD-####)。客户可用 customer_id 指定,或给 customer(邮箱/电话)自动匹配/创建;礼品订单支持 is_gift 相关字段。**含 draft 状态注记(REQ-20261027-05)**:新建订单恒为 `status='draft'` 并触发 `order.created` webhook(载荷 `status='draft'`);本端点的客户自动匹配/新建行为仅限本公开入口,Rollie 对话建单走内部执行端点且禁用该行为(见「Rollie 第二层写操作一期」节)。

POST/api/oms/orders/{id}/label-attachment

登记客供 label 附件(D64/REQ-20261029-28;以 action 注册经既有 [...action] catch-all 分发,URL 不变、OMS 路由净增 0):multipart file 或 JSON { file_key } 二选一+tracking_no*+carrier_code*(service_code 可选);五项校验缺一不可——PDF 首页 4×6in(±6pt,横竖向都认)/单页/tracking 必填/承运商必填/tracking 同组织内 active 唯一占用(被占回 409 tracking_taken、规格不合回 400 label_pdf_invalid,detail.reason 细分且文案均为大白话);文件落 Storage 桶 oms-order-labels;同单换新走 supersede(同 tracking 先失效旧行防自撞、不同 tracking 先登记成功再失效旧行)。**多包裹(D108 G3/REQ-20261104-05)**:可选 `package_seq`(第几包,multipart 字符串/JSON 数字都认,缺省 1,须 1..99 正整数、非法回 400 detail.reason='package_seq')——一单可为每个包裹各登记一份,换新只 supersede 同 seq 旧行、其他包裹不受影响;响应行带 `package_seq` 与 `original_format`(本批恒 'pdf',图片归一是 G2);同 seq 并发双占由 DB 部分唯一索引兜底回 409 `package_seq_taken`;两列由 migration 851 落(应用前防御降级:整单口径照常,显式登记 seq≥2 回 400 明示多包裹还没开通、不静默记成第 1 包)。权限 oms.orders create/edit

GET/api/oms/orders/{id}/label-attachment

本订单全部 label 附件行,data 直接回数组(active 优先,同状态内 created_at 新→旧),每行含 status(active/superseded/voided)全列与 `package_seq`/`original_format`(D108 G3,多包裹逐包呈现据此分组;列未就位时归一回 package_seq=1/original_format='pdf');订单不存在 404 ORDER_NOT_FOUND。权限同 POST

DELETE/api/oms/orders/{id}/label-attachment

作废附件:attachment_id 取 JSON body 或 query;行须属本组织+本订单,status→voided 并释放 tracking 占用;已 voided 重复作废幂等回 200(already_voided:true)。权限 oms.orders delete/edit

PATCH/api/oms/orders/{id}

两种模式:① {action} 走状态机(submit / approve / allocate / release / partial_fulfill / fulfill / deliver / cancel;非法流转 400);② {fields, lines} 编辑草稿(仅 draft/pending_review 可改,fields 走白名单,lines 整单替换并重算金额)。

PATCH/api/oms/orders/{id}

两种模式:① {action} 走状态机(submit / approve / allocate / release / partial_fulfill / fulfill / deliver / cancel;非法流转 400);② {fields, lines} 编辑草稿(仅 draft/pending_review 可改,fields 走白名单,lines 整单替换并重算金额)。

POST/api/oms/orders/{id}/dispatch/execute

执行分仓:按给定的分仓方案为订单建 WMS 出库单

POST/api/oms/orders/{id}/dispatch/preview

分仓试算:只读算出分仓方案,不写库

POST/api/oms/orders/{id}/fraud-clear

人工复核后清除订单的欺诈标记(认为是误报)

POST/api/oms/orders/{id}/fraud-confirm

确认订单为欺诈,可选把订单的联系信息自动加入黑名单

POST/api/oms/orders/{id}/fraud-mark

人工手动把订单标记为欺诈风险(不依赖黑名单匹配)

POST/api/oms/orders/{id}/fraud-recheck

手动对订单重新做一次欺诈检查

POST/api/oms/orders/{id}/hold

POST /api/oms/orders/[id]/hold — 单据 Hold(2026-10-20,migration 491):body `{reason_code, note?}`。Hold 是独立于状态链的标记(不改 status),拦 allocate/release/submit/push-to-wms/dispatch/ship/mark-shipped/split/改 lines;原因走主数据 `shared_reason_codes` category=`order_hold`。Hold 时自动向关联 wms_shipments 传导(来源标记 oms);unhold 只解除传导位。留痕 oms_order_status_audit(note=`HOLD/UNHOLD …`)。错误码:ORDER_ALREADY_ON_HOLD / ORDER_NOT_ON_HOLD / ORDER_HOLD_TERMINAL / HOLD_REASON_REQUIRED / HOLD_REASON_INVALID。关联端点 `/api/oms/orders/{id}/unhold` 同体。

GET/api/oms/orders/{id}/label

取 4x6 shipping label 面单数据(standalone 直发,前端渲染打印)

POST/api/oms/orders/{id}/mark-shipped

外部打单后手动标记发货,并录入外部 tracking 号

POST/api/oms/orders/{id}/packing-list

生成装箱单 payload 并落库(不调真实打印)

GET/api/oms/orders/{id}/pick-list

取纸质拣货单数据(订单+行+每行推荐库位)

POST/api/oms/orders/{id}/push-to-wms

把订单推送到 WMS 履约(仅 wms_sync 模式,订单变为 released)

POST/api/oms/orders/{id}/recheck-intake

POST /api/oms/orders/[id]/recheck-intake — 订单源头完整性复检(REQ-20261031-22):对单张订单立即重跑统一校验(实现 apps/oms/lib/order-intake-validation.ts,建单/改单已自动复检,本端点供详情页「重新检查」与异常处置兜底)。返回 `{order_id, skipped, issues[], check, has_issues}`;终态订单 skipped='terminal' 不回溯改判;权限 oms.orders edit(复检会覆写两列,按写操作设权)。响应同时即落库后的 intake_issues/intake_check。配套口径:GET /api/oms/orders 加 `intake_issue=1` 异常筛选、行/详情 DTO 带 intake_issues+intake_check;ship/mark-shipped 在 intake_issues 非空时 409 ORDER_INTAKE_INCOMPLETE、batch-ship 逐单同 code 排除;push-to-wms 成功响应在 data 注入 intake_warning{issue_count, issue_codes}(放行带提示)。

PUT/api/oms/orders/{id}/freight

出货三方式(REQ-20261025-03):standalone freight 手工数据保存(底座校验一处,OMS 界面与 Orderball 门面共用)。body `{carrier?, pro_no?, pickup_at?, freight_term?(prepaid/collect/third_party), freight_class?, pallets*[≥1 托,逐托 gross_weight_kg/length_cm/width_cm/height_cm 传了须 >0], write_back_item_dims?}`;汇总以逐托为准重算后整段存 `custom_fields.freight`;`write_back_item_dims=true` 且整单单产品单托时把尺寸/单件重回写 wms_items 空值列。错误:`NOT_STANDALONE_MODE`(wms_sync)、`FREIGHT_TERM_INVALID`、`PALLETS_REQUIRED`、`INVALID_PALLET_MEASURE`。终态守卫(REQ-20261031-73):订单 status ∈ shipped/fulfilled/delivered/cancelled 时回 409 `ORDER_NOT_EDITABLE`(发货后 freight 数据冻结,与门面只读态同口径)。Orderball 门面 Freight「确认发货」走既有 `mark-shipped`(carrier=freight.carrier、tracking=PRO 号),无新底座端点。

POST/api/oms/orders/{id}/pickup-ready

出货三方式(REQ-20261025-03):standalone 客户自提「备好待取」。写订单 `custom_fields.pickup`(ready_at 只记第一次+联系人/备注),**不扣库存、不改订单主状态**,audit 留痕。错误:`NOT_STANDALONE_MODE`(wms_sync 去 WMS 侧办)、`WRONG_ORDER_TYPE`(非 will_call 单)。已 fulfilled 回既有结果。写段成功后即时复检入境校验(REQ-20261031-27,`recheckOrderIntakeQuiet`):ready 登记的提货联系人即时消 will_call 联系人类异常标,复检失败只记日志不影响 ready 结果。**二期交接证据(REQ-20261031-28,设计 §12)**:ready 成功后落证据行(档位快照,simple/standard/strict 按货主级>组织默认解析);标准/严格档生成 6 位提货码并短信通知联系人(响应加 `pickup_tier`、`code_sent_via`='sms'|'none',仅真送达记 sms);证据层失败回 `PICKUP_READY_FAILED`(段已写、ready 可安全重试收敛)。

GET/api/oms/orders/{id}/freight

出货三方式(REQ-20261025-03 / D20 §3.3):standalone freight 数据回读/预填。standalone 且无保存值时按订单行×产品主数据(wms_items 单件长宽高重)回 prefill(总重/总体积/建议托盘数=max(⌈体积÷1.5m³⌉, ⌈总重÷500kg⌉)/逐托初值/密度建议 class/缺失字段清单);有保存值回 `saved`(订单 `custom_fields.freight` 段)。wms_sync 回 `{mode:'wms_sync', shipments:[出库单号/状态/自提状态]}` 只读呈现。

PUT/api/oms/orders/{id}/freight

出货三方式(REQ-20261025-03):standalone freight 手工数据保存(底座校验一处,OMS 界面与 Orderball 门面共用)。body `{carrier?, pro_no?, pickup_at?, freight_term?(prepaid/collect/third_party), freight_class?, pallets*[≥1 托,逐托 gross_weight_kg/length_cm/width_cm/height_cm 传了须 >0], write_back_item_dims?}`;汇总以逐托为准重算后整段存 `custom_fields.freight`;`write_back_item_dims=true` 且整单单产品单托时把尺寸/单件重回写 wms_items 空值列。错误:`NOT_STANDALONE_MODE`(wms_sync)、`FREIGHT_TERM_INVALID`、`PALLETS_REQUIRED`、`INVALID_PALLET_MEASURE`。

POST/api/oms/orders/{id}/pickup-ready

出货三方式(REQ-20261025-03):standalone 客户自提「备好待取」。写订单 `custom_fields.pickup`(ready_at 只记第一次+联系人/备注),**不扣库存、不改订单主状态**,audit 留痕。错误:`NOT_STANDALONE_MODE`(wms_sync 去 WMS 侧办)、`WRONG_ORDER_TYPE`(非 will_call 单)。已 fulfilled 回既有结果。写段成功后即时复检入境校验(REQ-20261031-27,`recheckOrderIntakeQuiet`):ready 登记的提货联系人即时消 will_call 联系人类异常标,复检失败只记日志不影响 ready 结果。**二期交接证据(REQ-20261031-28,设计 §12)**:ready 成功后落证据行(档位快照,simple/standard/strict 按货主级>组织默认解析);标准/严格档生成 6 位提货码并通知联系人(body 可带 `pickup_contact_email`,缺省链:入参→段现值→客户邮箱;**2026-10-31 扩展双通道(REQ-20261031-55)**:有邮箱先发邮件——发件显示名用组织名、内容含单号/码/提货地点,仅真发成功记 `code_sent_via`='email';邮件未配置/失败或无邮箱回落短信,仅真送达记 'sms';皆无记 'none' 不阻塞 ready。响应加 `pickup_tier`、`code_sent_via`);证据层失败回 `PICKUP_READY_FAILED`(段已写、ready 可安全重试收敛)。

POST/api/oms/orders/{id}/pickup-code-resend

二期交接证据(REQ-20261031-28):重发提货码——换新码(旧码即失效)、`code_resent_count`+1、按新码重新通知(邮件优先、回落短信,口径同 ready;邮件与卡面同源同码)。仅 standalone 待取态(已 ready 未取走)且档位需码;不重置输错次数、不解锁定(响应 `code_locked` 明示)。错误:`NOT_STANDALONE_MODE`、`PICKUP_NOT_READY`、`PICKUP_CODE_NOT_REQUIRED`(无证据行/简易档)。留痕 auditOrder。

POST/api/oms/orders/{id}/pickup-code-unlock

二期交接证据(REQ-20261031-28):主管重置提货码。body `{supervisor_id*, supervisor_password*}`——主管资格(管理员/所有者或主管级岗位)+验主管本人密码+批准人≠操作人(共享件 `@docklify/auth/supervisor-approval`,与 WMS 同配方);成功后输错清零、解锁定、换新码并通知(未锁定态亦可执行=受控换码,留痕)。错误:`SUPERVISOR_REQUIRED`/`SUPERVISOR_SELF`/`SUPERVISOR_NOT_ELIGIBLE`/`SUPERVISOR_PASSWORD_INVALID`、`NOT_STANDALONE_MODE`、`PICKUP_NOT_READY`、`PICKUP_CODE_NOT_REQUIRED`。

GET/api/oms/orders/{id}/pickup-approvers

二期交接证据(REQ-20261031-28):有资格主管名单(解锁选人用),形状与 WMS `/api/wms/supervisor-approvers` 一致 `{items:[{user_id, display_name, email, employee_no}], total}`,过滤无可读标识者;非 will_call 或非 standalone 回空名单。

POST/api/oms/orders/{id}/pickup-contact

提货联系人维护(三期,REQ-20261031-55):只改 `custom_fields.pickup` 段的联系人三项,不推进任何状态。body `{pickup_contact_name?, pickup_contact_phone?, pickup_contact_email?}`(兼容同名无前缀键)——给了才改、显式 null/空串=清空该项;邮箱格式非法 400 `INVALID_PICKUP_EMAIL`(人话文案)。用途:建单漏填/备货后改错——ready 前后均可(complete 的 intake 拦截只看 name/phone,email 不列必填)。写后即时复检 intake 消标+auditOrder 留痕;无任何字段回 `unchanged: true`。错误:`NOT_STANDALONE_MODE`、`WRONG_ORDER_TYPE`、`PICKUP_CONTACT_FAILED`。

GET/api/oms/orders/{id}/pickup-evidence

二期交接证据(REQ-20261031-28):交接证据视图。standalone→本单证据行;wms_sync→关联 will_call 出库单证据行(只读,拆单选择:已完成证据最新>有证据行>最近 ready,响应带 `shipment_no`/`shipment_id` 标注来源)。pending 视图含档位/码状态(本单路径含码,wms_sync 路径不下发码);completed 视图为整包证据(码核销时间、取货人+代取标记、签名图 600 秒 signed URL、证件查验记录、经办人、完成时间);无证据/已取消回 `handover: null`(cancelled 触发惰性清理)。

POST/api/oms/orders/{id}/retry-tracking-sync

手动重试 tracking 回传渠道

GET/api/oms/orders/{id}/ship

查订单是否可发货,并列出可用的承运商账号与服务

POST/api/oms/orders/{id}/ship

standalone 直发:扣库存、生成 tracking 号,订单变为 fulfilled

GET/api/oms/orders/{id}/serial-check

SN 扫入即时校验:对订单某行产品查库存 SN 台账单点校验(REQ-20261030-27,与 ship 出单复核同一实现)

POST/api/oms/orders/{id}/void-label

本地作废一个包裹的面单:在订单 shipping 段内打 voided_at+时间线留痕(REQ-20261030-27,D10;不调承运商、不回滚库存/SN)

POST/api/oms/orders/{id}/update-ship-to

出单前修正收件地址(REQ-20261030-27,Packing Station A1):通用草稿编辑只许 draft,打包台载入的是 allocated/released 待发单,故开此窄口——只放行 ship_to_* 七字段,未出单前(draft/confirmed/allocated/released)可改,已履约/已取消回 NOT_EDITABLE;留痕 oms_order_status_audit(note=SHIP_TO_UPDATED)

POST/api/oms/orders/{id}/split-by-item

一单一品:按商品把订单拆成多个子订单

GET/api/oms/orders/{id}/timeline

拉取订单的状态流转审计时间线

GET/api/oms/orders/{id}/wms-timeline

WMS 履约进度时间线(wms_sync 模式订单)。读 WMS worker 回写的镜像表 oms_wms_status_events,按时间倒序返回 committed → picking → picked → packed → shipped(带 tracking 号)→ delivered;镜像表不存在/查询失败时返回空数组 + pending_table: true,不报错。

GET/api/oms/orders/{id}/routing

GET /api/oms/orders/[id]/routing — 订单详情 Routing 区只读投影(528):{ decision(最近路由决策 + 规则名/仓名), order_warehouse(订单头当前仓), allocations_summary(按仓聚合 + reason 枚举), shipments(出库单 + warehouse_code + lines + events), dispatch_plan(最近分仓计划留痕), degraded(子块降级标记数组:decision/allocations/shipments/shipment_lines/shipment_events/dispatch_plan,非空 = 该块查询失败、数据不全) };子块缺失优雅降级不 500。Perm: `oms.orders` view。

POST/api/oms/orders/batch-cancel

批量取消销售订单,最多 100 个

POST/api/oms/orders/batch-ship

批量发货(standalone 直发),最多 100 单,单单失败不影响其他

POST/api/oms/orders/import

用前端解析好的行数据批量导入销售订单(草稿)。**行校验(REQ-20261106-22 批一)**:导入行单位由产品自身单位派生并逐组校验,非法组整组失败、按既有 failed 形状记 `INVALID_LINE_UOM`。

POST/api/oms/orders/merge

确认合单:把多个订单的行并到最早创建的订单里;需组织设置 merge_rule 开启,关闭时 400 FEATURE_DISABLED(开关只管手动合单入口,REQ-20261023-38)

POST/api/oms/orders/merge-preview

合单预览:只算可合并组和冲突原因,不改数据;需组织设置 merge_rule 开启,关闭时 400 FEATURE_DISABLED(REQ-20261023-38)

GET/api/oms/orders/volume

按天/周/月/年聚合订单量趋势

GET/api/oms/orders/{id}

订单详情:订单行(含 item: {id, sku, name} 展开)、客户/渠道展开、inventory_source(wms_sync/oms_standalone,决定是否展示"推送到 WMS")、关联的 WMS 出库单(wms_shipment 首单向后兼容 + wms_shipments 全部)、merchant_warehouses(该货主候选仓库,供 allocate 选仓)。

客户/api/oms/customersGETPOSTPATCHDELETE5 个接口

GET/api/oms/customers

按关键字或启用状态筛选,分页拉取客户主数据列表

POST/api/oms/customers

新建客户,code 必填且在本组织内唯一

DELETE/api/oms/customers/{id}

软删客户(置 is_active=false,不物理删除)

GET/api/oms/customers/{id}

拉取单个客户的详情

PATCH/api/oms/customers/{id}

更新客户字段,改 code 时校验同组织唯一

退货16 个接口

退货单/api/oms/rmasGETPOSTPATCH12 个接口

GET/api/oms/rmas

分页拉取 OMS 退货单列表(退货一期新增来源/路由/执行/派生四维筛选与行级理由待映射派生标记)

POST/api/oms/rmas

手工新建 OMS 退货单(退货一期单一入口:改走入境服务 ingestReturn 落单,source_kind='manual';单号 RMA-YYYYMMDD-#### 自动生成)。幂等口径:手工型不走入境幂等键,防重复靠建单校验——同订单 + 同行 + 未终结单(状态不在 completed/cancelled/rejected)存在时 409 阻止。单号序号口径(2026-10-25,REQ-20261025-07):#### 为**全表跨组织**当日全局序号(与唯一索引 rmas__rma_no 对齐),非组织内序号;同日不同组织的单号连续递增、互不重复(此前按组织取号与全局唯一索引冲突、跨组织建单 500 已修,POST /api/rms/rmas 同链受益)

GET/api/oms/rmas/{id}

拉取 OMS 退货单详情(退货一期:附物流时间线与关联 RMS 执行单双显键)

PATCH/api/oms/rmas/{id}

存量状态动作端点(批准/收货/完成/驳回)。退货一期 P2-7 收口注记:本端点不再直写 oms_rmas.status——目标值先做旧值映射(RMA_ACTIONS 的 receive 仍定义为 receiving、落库映射为现行值 received;approve→approved、complete→completed、reject→rejected 同名直传),再经状态唯一写者 applyTransition 推进;receiving 仅作兼容读(存量 receiving 行仍可 complete)。本端点无非 status 字段的写路径,成功响应仍为整行 RMA,详情页头部按钮契约不变;新的人工动作一律走 POST /api/oms/rmas/{id}/<action> 动作端点组

POST/api/oms/rmas/{id}/assign-warehouse

人工定仓(退货路由三级的人工队列出路):给未定仓退货单选仓定仓;可选把这次定仓沉淀为二级规则

POST/api/oms/rmas/{id}/reroute

人工改仓:只改路由轴(assigned_warehouse_id / routing_status / assignment_source),不动主状态

POST/api/oms/rmas/{id}/retry-derivation

派生失败重派:对 wms 模式、已定仓、派生未完成的退货单重新派生 RMS 执行单(派生本身幂等可续,已派生不重复建单)

POST/api/oms/rmas/{id}/receive-confirm

standalone 收货确认 + 两档简易判定(oms_standalone 专用;深度质检不在 standalone 提供):确认到货并逐行标可再售/破损,状态推 received → inspecting 并落到仓时间线事件

POST/api/oms/rmas/{id}/refund-conclusion

记录退款结论(退货默认策略:只记结论与 refund_status,**不在此执行退款**——退款实际执行默认在平台侧,渠道可配直退除外;响应 note 明示此口径)。inspecting 时顺推 resolved

POST/api/oms/rmas/{id}/replay-callback

结果回传重放。一期口径(如实标注):尚无真实平台回传通道,本动作只落一条 simulated 时间线事件(event_code=callback_replay_simulated、source='simulated')并返回 simulated=true,不谎报已回传;二期接通真实回传后改走回传通道重放(回传幂等键为 (rma_id, trigger_point))

POST/api/oms/rmas/{id}/reopen

人工重开(状态机唯一回退路径,仅人工可触发,系统事件永不回退):completed / cancelled → requested,必选原因并留痕;wms 模式且 RMS 执行单停在终态时同步回退执行单(双向接通)

POST/api/oms/rmas/{id}/link-order

人工关联原订单(「未对上原订单」降级标记的出路):补 order_id 与关联兜底字段、行级 so_line_id 按 SKU 尽力对齐;不写主状态

Return Routing Rules/api/oms/return-routing-rulesGETPOSTPATCHDELETE4 个接口

GET/api/oms/return-routing-rules

退货路由二级规则列表(priority 升序、同优先级按创建时间升序)

POST/api/oms/return-routing-rules

新建退货路由规则。防冲突校验:同条件组合(货主/类目/渠道/来源四维全等)不得指向两个目的地;目标域只有仓库与地址快照(叶子、无规则间引用),结构上无环。一期 external 目标只落人工队列预填、不自动寄外部地址

PATCH/api/oms/return-routing-rules/{id}

更新退货路由规则(部分字段;先与存量合并再整体校验,改后仍启用时参与同条件冲突校验并排除自身)

DELETE/api/oms/return-routing-rules/{id}

停用退货路由规则(软停 is_active=false,不真删,保留历史可复核;重新启用走 PATCH is_active=true)

分仓与定价25 个接口

分仓路由/api/oms/routingGETPOSTPUTPATCHDELETE9 个接口

GET/api/oms/routing

拉取销售订单路由配置总览(通用设置 + 自定义规则)

POST/api/oms/routing/preview

路由试算:跑完整路由引擎(含库存 ATP 检查),不写库

POST/api/oms/routing/rule

新建自定义路由规则

DELETE/api/oms/routing/rule/{id}

删除自定义路由规则

PATCH/api/oms/routing/rule/{id}

更新自定义路由规则(部分字段;conditions 整体替换)

PUT/api/oms/routing/settings

保存销售订单路由的通用设置

GET/api/oms/routing/zones

拉取邮编区间→仓库的映射列表(zip_code_routing 策略用)

POST/api/oms/routing/zones

新建邮编区间→仓库的映射

DELETE/api/oms/routing/zones/{id}

删除邮编区间→仓库的映射

定价/api/oms/pricingGETPOSTPUTPATCHDELETE16 个接口

GET/api/oms/pricing/price-lists

OMS 商品定价 — 价目表列表(分页;query: scope=channel|client / status / channel_id / client_id / q 名称模糊 / limit / offset;返回头字段 + item_count 行数与 total)。Perm: `oms.settings` view。

POST/api/oms/pricing/price-lists

OMS 商品定价 — 新建价目表(带行 `items: [{item_id, unit_price, min_qty?}]`,min_qty 为数量阶梯起量;scope=channel 须带 channel_id、scope=client 须带 client_id,可带 customer_id 收窄到单个买家;单表行数上限 5,000;同目标同名新建不拦截、响应带 warning 提示)。Perm: `oms.settings` create+edit。

GET/api/oms/pricing/price-lists/{id}

OMS 商品定价 — 价目表详情(头 + 全部行,行带 SKU / 商品名)。Perm: `oms.settings` view。

PATCH/api/oms/pricing/price-lists/{id}

OMS 商品定价 — 更新价目表(头字段可改,含归属 scope / channel_id / client_id / customer_id;带 items 时整体替换全部行,单事务完成、中途失败不清空;响应带回最新 updated_at)。Perm: `oms.settings` create+edit。

DELETE/api/oms/pricing/price-lists/{id}

OMS 商品定价 — 删除价目表(物理删除,行级联删;已下单订单行上的价格快照不受影响)。Perm: `oms.settings` delete+edit。

GET/api/oms/pricing/promotions

OMS 商品定价 — 活动价列表(分页;query: scope=all|channel|client / status / channel_id / client_id / q / limit / offset;返回头字段 + item_count 与 total)。Perm: `oms.settings` view。

POST/api/oms/pricing/promotions

OMS 商品定价 — 新建活动价(带行 `items: [{item_id, promo_price, min_qty?}]`;starts_at / ends_at 必填且起 < 止,活动价必须有时间窗;行上限 5,000)。Perm: `oms.settings` create+edit。

GET/api/oms/pricing/promotions/{id}

OMS 商品定价 — 活动价详情(头 + 全部行,行带 SKU / 商品名)。Perm: `oms.settings` view。

PATCH/api/oms/pricing/promotions/{id}

OMS 商品定价 — 更新活动价(头字段可改;带 items 时整体替换全部行,单事务完成;响应带回最新 updated_at)。Perm: `oms.settings` create+edit。

DELETE/api/oms/pricing/promotions/{id}

OMS 商品定价 — 删除活动价(物理删除,行级联删;已下单订单的价格快照不受影响)。Perm: `oms.settings` delete+edit。

POST/api/oms/pricing/resolve

OMS 商品定价 — 取价试算:body `{ item_id*, qty?, currency?(默认 USD), channel_id?, client_id?, customer_id?, at? }`;返回命中的单价、币种与价格来源(promo 活动价 / channel_list 渠道价目表 / client_list 客户价目表 / base 基础价),任何一层都无价返回 null。Perm: `oms.settings` view。

GET/api/oms/pricing/channel-settings

OMS 商品定价 — 价格主导方配置列表:返回全部渠道及各自配置;未配置过的渠道按缺省返回(price_authority=platform_master 平台主导、compare_enabled=true、configured=false)。Perm: `oms.settings` view。

PUT/api/oms/pricing/channel-settings

OMS 商品定价 — 批量保存价格主导方配置:body `{ items: [{ channel_id, price_authority: oms_master|platform_master, compare_enabled }] }`,按渠道逐条保存。Perm: `oms.settings` create+edit。

GET/api/oms/pricing/comparisons

OMS 商品定价 — 价格对照结果列表(读已留存的对照结果,不现算;query: channel_id / limit / offset;行含 SKU、商品名、渠道名、OMS 价、平台价、差异比例 diff_pct 与对照时间 checked_at)。Perm: `oms.settings` view。

POST/api/oms/pricing/comparisons/run

OMS 商品定价 — 立即对照一次:body `{ channel_id }`;把平台现价拉回、与 OMS 取价逐个商品比对并留存结果,返回 `{ compared, differences, skipped, failed, checked_at }`;仅支持 Shopify 渠道,其他渠道返回「暂不支持」;该渠道对照开关关闭时报错提示先去打开。Perm: `oms.settings` create+edit。

GET/api/oms/pricing/item-prices

OMS 商品定价 — 某商品的现价一览:query `item_id*`;返回该商品在各生效价目表与活动价中的价格行(名称、类型、范围、币种、价格、阶梯起量),供产品页价格区只读展示。Perm: `oms.settings` view。

库存与产品20 个接口

库存/api/oms/inventoryGETPOST9 个接口

GET/api/oms/inventory

查 OMS 库存(独立库存可调整;WMS 同步模式只读)

POST/api/oms/inventory/adjust

调整 OMS 独立库存数量,走审批流(仅 standalone 模式)

POST/api/oms/inventory/adjust-condition

把库存数量在 available/hold/damaged 三个状态桶之间转移

POST/api/oms/inventory/adjust-cost

调整 OMS 独立库存的单位成本,走审批流(仅 standalone 模式)

GET/api/oms/inventory/adjustments

拉取库存调整审批单列表

POST/api/oms/inventory/adjustments

建库存调整审批单的通用入口(数量/成本/状态三型)

POST/api/oms/inventory/adjustments/{id}/approve

批准库存调整单并使其生效(draft → approved)

POST/api/oms/inventory/adjustments/{id}/reject

驳回库存调整单(draft → rejected)

GET/api/oms/inventory/history

查 OMS 独立库存的调整历史流水

产品/api/oms/productsGETPOSTPATCHDELETE7 个接口

GET/api/oms/products

按关键字、启用状态筛选,分页拉取产品主数据(与 WMS 共用)

POST/api/oms/products

新建产品,SKU 在本组织内不可重复

DELETE/api/oms/products/{id}

软删产品(置 is_active=false,不影响 WMS 历史单据)

GET/api/oms/products/{id}

拉取单个产品的详情

PATCH/api/oms/products/{id}

更新产品(白名单字段;SKU 建后不可改,传了会忽略)

GET/api/oms/products/{id}/costs

产品当前解析成本(按币种)+成本行历史(报表 P3 B1 / D81 §3.1)。current 直接由底座成本服务 resolveItemCosts 解析(单一事实源,本端点不另建降级口径):manual 人工订正恒居最上,其余默认最近采购价 po_last 优先于商品标准成本 item_standard、同源内取 effective_at 最新;按币种分别解析、绝不跨币种合并;该产品没有任何成本行时 current 为空数组(如实呈现无成本,不按 0 估值)。权限隔离:requirePerms `oms.settings` view(与产品详情同口径);产品按当前组织+标准版默认货主限定查存在性,跨组织 id 按 404 处理。

POST/api/oms/products/{id}/costs

人工订正产品成本(报表 P3 B1 / D81 §3.1):落一行 manual 成本行(经底座 recordItemCost,ON CONFLICT 同 org×item×source×effective_at 不重复落),manual 行在解析序中恒居最上、落行即生效。权限隔离:requirePerms `oms.settings` create+edit(与产品保存同口径);产品存在性校验同 GET。

物品/api/oms/itemsGETPOSTDELETE4 个接口

GET/api/oms/items

商品下拉框用的轻量商品列表(订单表单用)

DELETE/api/oms/items/{id}/uoms

删除某商品的一行多单位换算。**行为变更(REQ-20261106-22 批一)**:按规范码定位(传 each 也命中 EA 行);删除前过 inside+单据行双守卫,被引用时 400 `UOM_IN_USE`(被引用只能停用)。

GET/api/oms/items/{id}/uoms

查某商品的可用计量单位列表(订单行 UOM 下拉用)

POST/api/oms/items/{id}/uoms

给某商品新增一行多单位换算。**行为变更(REQ-20261106-22 批一)**:uom_code 落库 canonical(EACH→EA);新行与现有行做整组校验(base 钉 1、inside 链复算与直填强一致、恰一 default——无默认时 base 补默认);未登记码自动登记字典。

设置24 个接口

设置/api/oms/settingsGETPOSTPUTPATCHDELETE11 个接口

GET/api/oms/settings/adjust-reasons

拉取租户的库存调整理由列表

POST/api/oms/settings/adjust-reasons

新增一条库存调整理由

DELETE/api/oms/settings/adjust-reasons/{id}

删除一条库存调整理由

PATCH/api/oms/settings/adjust-reasons/{id}

更新一条库存调整理由

DELETE/api/oms/settings/auto-approve

把 merchant 从自动审核列表中移除

GET/api/oms/settings/auto-approve

拉取自动审核的 merchant 列表

POST/api/oms/settings/auto-approve

把 merchant 加入自动审核列表

GET/api/oms/settings/inventory-source

拉取库存来源配置(租户默认 + 各仓库覆盖)

PUT/api/oms/settings/inventory-source

保存库存来源配置

GET/api/oms/settings/tenant

拉取租户级 OMS 设置

PATCH/api/oms/settings/tenant

更新租户级 OMS 设置

Fraud Blacklist/api/oms/fraud-blacklistGETPOSTPUTDELETE8 个接口

GET/api/oms/fraud-blacklist

按类型、风险等级、状态筛选黑名单条目列表

POST/api/oms/fraud-blacklist

新增一条黑名单条目,服务端自动计算归一化值

DELETE/api/oms/fraud-blacklist/{id}

停用黑名单条目(置 is_active=false,不物理删除)

GET/api/oms/fraud-blacklist/{id}

拉取单个黑名单条目的详情

PUT/api/oms/fraud-blacklist/{id}

编辑黑名单条目,改 value 或类型时重算归一化值

GET/api/oms/fraud-blacklist/{id}/hits

查某条黑名单命中过的订单列表

GET/api/oms/fraud-blacklist/export

把全部活跃黑名单条目导出为 CSV 文件

POST/api/oms/fraud-blacklist/import

用 CSV 文件批量导入黑名单条目

承运商/api/oms/carriersGETPOSTPATCHDELETE5 个接口

GET/api/oms/carriers

按状态或承运商代码筛选,分页拉取本组织的快递账号列表(数据源已统一为 Master Data 承运商账号 shared_carrier_accounts,REQ-20261027-17)

POST/api/oms/carriers

新建快递账号,承运商代码必须在预置目录里

DELETE/api/oms/carriers/{id}

删除快递账号,账号凭证会级联删除

PATCH/api/oms/carriers/{id}

更新快递账号的账号号、打单模式、状态、启用服务或默认标记

POST/api/oms/carriers/{id}/test

对快递账号做一次模拟连通性测试,并记录测试时间与结果

通用35 个接口

Channels/api/oms/channelsGETPOSTPUTPATCHDELETE10 个接口

DELETE/api/oms/channels/{id}

DELETE /api/oms/channels/{id} — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/connections/{id},参数与语义以原件为准;租户会话鉴权

GET/api/oms/channels

GET /api/oms/channels — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/connections,参数与语义以原件为准;租户会话鉴权

GET/api/oms/channels/{id}/secrets

GET /api/oms/channels/{id}/secrets — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/connections/{id}/secrets,参数与语义以原件为准;租户会话鉴权

PATCH/api/oms/channels/{id}

PATCH /api/oms/channels/{id} — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/connections/{id},参数与语义以原件为准;租户会话鉴权

POST/api/oms/channels

POST /api/oms/channels — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/connections,参数与语义以原件为准;租户会话鉴权

POST/api/oms/channels/{id}/pull-orders

POST /api/oms/channels/{id}/pull-orders — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/connections/{id}/pull-orders,参数与语义以原件为准;租户会话鉴权

POST/api/oms/channels/{id}/push-products

POST /api/oms/channels/{id}/push-products — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/connections/{id}/push-products,参数与语义以原件为准;租户会话鉴权

POST/api/oms/channels/{id}/sync-inventory

POST /api/oms/channels/{id}/sync-inventory — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/connections/{id}/sync-inventory,参数与语义以原件为准;租户会话鉴权

POST/api/oms/channels/{id}/test

POST /api/oms/channels/{id}/test — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/connections/{id}/test,参数与语义以原件为准;租户会话鉴权

PUT/api/oms/channels/{id}/secrets

PUT /api/oms/channels/{id}/secrets — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/connections/{id}/secrets,参数与语义以原件为准;租户会话鉴权

调度/api/oms/dispatchGETPOSTPATCHDELETE4 个接口

GET/api/oms/dispatch/rules

按优先级升序列出分仓规则

POST/api/oms/dispatch/rules

新建一条分仓规则

DELETE/api/oms/dispatch/rules/{id}

删除分仓规则,不允许删最后一条启用的规则

PATCH/api/oms/dispatch/rules/{id}

更新分仓规则的任意字段

Email Intake/api/oms/email-intakeGETPOST3 个接口

GET/api/oms/email-intake/cases

邮件收单列表:按 status / from(发件人模糊)/ client_id / from_date / to_date 检索,.range 分页+count(steer 2026-10-30 08:10 检索口径)。

GET/api/oms/email-intake/cases/{id}

处理单详情:处理单 + 往返时间线(逐封正文/当轮抽取/字段增减)+ 附件归档 + 关联订单 + 绑定货主产品清单(确认面指认用)。

POST/api/oms/email-intake/cases/{id}/actions

确认面动作:confirm(可带改后 fields/lines;无单时经管线同口径 createSalesOrder 建草稿,再 advanceDraftOrder 沿既有状态路径生效;ATP 不足停待审核并如实回执)/ reject(关闭处理单;D75 起同时吊销该单客人链接)/ map_line(行指认并落映射记忆 email_intake_sku_mappings)/ retry(人工重新处理,复用 resumeCase)/ revoke_guest_links(必填 reason,吊销该单全部客人链接)/ reissue_guest_link(旧链保留可用+新签一条,D-EL3)/ approve_verification(D75 待验真通过:client_id+trust_level → 发件人落 verified 后 resumeCase 续跑)/ reject_verification(必填 reason → 发件人 disabled+关单+最简模板)。人工动作审计记真实用户。**REQ-20261031-74 加法扩**:能力处理单(查库存/拉货源/取消单,pending_review)confirm/reject 专属语义——confirm 按能力真执行(查库存发管线备好的库存答复、拉货源此刻真拉、取消走 executeOrderAction cancel+customer_requested 并如实回执成败,失败 409 不关单)后回信关单;reject 回「未办理」告知信+关单(能力单专用,销售单 reject 口径不变);审计 capability_confirmed/capability_rejected。Orderball 门面经自有转发路由调本端点(case_id 只进路径)。

Shipping/api/oms/shippingGETPOST3 个接口

POST/api/oms/shipping/rates

实时比价:UPS 直连 + 聚合商三路并发查运费

POST/api/oms/shipping/rate-quotes

比价留痕落库(REQ-20261025-02,设计 D19 §3.1/§3.3;表 oms_rate_quote_logs,migration 558):body { order_id*(须本组织订单,否则 404 ORDER_NOT_FOUND), order_no?, carrier_account_id?, request?, quotes*(数组), selected*(对象), tracking_number? };按 (organization_id, order_id) 幂等——已有行直接返回并带 `existed: true`,insert 撞唯一键再查返回既有行。Perm: `oms.orders` create+edit。

GET/api/oms/shipping/rate-quotes

比价留痕回查(REQ-20261025-02,设计 D19 §3.3):query `order_id` 单查或 `order_ids`(逗号分隔、去空、最多 100)批量查;Resp `{ items: [...] }`(created_at 升序);无留痕返回空数组(不是错误)。Perm: `oms.orders` view。

Inventory Source/api/oms/inventory-sourceGETPOST2 个接口

GET/api/oms/inventory-source

拉取库存来源配置列表(租户默认 + 按仓库覆盖)

POST/api/oms/inventory-source

新建或更新库存来源配置(warehouse_id 为空表示租户默认)

Dashboard/api/oms/dashboardGET2 个接口

GET/api/oms/dashboard/sales-over-time

OMS Dashboard 销售趋势:本期 vs 对比期双系列聚合(Andy 2026-10-19 新增)

GET/api/oms/dashboard/top-channels

OMS Dashboard 渠道排行:按渠道分组的销售额/订单数/件数及占比,含对比期销售额涨跌(Andy 2026-10-19 新增)

Return Reason Mappings/api/oms/return-reason-mappingsGETPUT2 个接口

GET/api/oms/return-reason-mappings

平台理由映射列表;`?unmapped=1` 为未映射 Top N 维护视图(standard_reason_code 为空、按 hit_count 降序,与入境未映射计数同表同源);响应附带组织退货执行模式当前生效值

PUT/api/oms/return-reason-mappings

按四元组补/改平台理由映射(upsert,冲突键 organization_id+source_kind+provider_code+platform_reason_code):运营补映射的写入口;补上后后续入境自动命中该标准码,存量已落 other 的行不回溯改写

Catalog/api/oms/catalogGET2 个接口

GET/api/oms/catalog/carriers

GET /api/oms/catalog/carriers — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/catalog/carriers,参数与语义以原件为准;租户会话鉴权

GET/api/oms/catalog/channels

GET /api/oms/catalog/channels — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/catalog/channels,参数与语义以原件为准;租户会话鉴权

Mappings/api/oms/mappingsGETPOST2 个接口

GET/api/oms/mappings

GET /api/oms/mappings — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/mappings,参数与语义以原件为准;租户会话鉴权

POST/api/oms/mappings

POST /api/oms/mappings — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/mappings,参数与语义以原件为准;租户会话鉴权

Sync Rules/api/oms/sync-rulesGETPOST2 个接口

GET/api/oms/sync-rules

GET /api/oms/sync-rules — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/sync-rules,参数与语义以原件为准;租户会话鉴权

POST/api/oms/sync-rules

POST /api/oms/sync-rules — 兼容别名(S2 代理 shim):转发 integration 域 /api/integration/sync-rules,参数与语义以原件为准;租户会话鉴权

Wms Status Callback/api/oms/wms-status-callbackPOST1 个接口

POST/api/oms/wms-status-callback

第三方 WMS 状态回传 webhook(无登录 session,用 API key 鉴权)

Internal/api/oms/internalPOST1 个接口

POST/api/oms/internal/tracking-sync

站间内部端点(活路由在 apps/oms,内部令牌鉴权):`{order_id}` → 转发 OMS 既有 triggerTrackingSync 做渠道 tracking 回写(G-09 包裹回写经此单点,不另造回写逻辑)

采购管理

采购订单20 个接口

订单/api/purchase/ordersGETPOSTPATCHDELETE12 个接口

GET/api/purchase/orders

分页查询采购单列表,支持按状态/供应商/仓库/货主/单号/日期筛选,并附带每单收货进度

POST/api/purchase/orders

新建采购单(草稿状态,含明细行),单号由系统自动生成

DELETE/api/purchase/orders/{id}

删除草稿采购单(非草稿状态不能删,需走取消流程)

GET/api/purchase/orders/{id}

查采购单详情,含明细行、供应商/仓库信息、关联的 WMS 入库单和 ASN、邮件事件时间线

PATCH/api/purchase/orders/{id}

更新采购单(仅草稿状态可改);传 lines 则整体替换明细行并重算金额

POST/api/purchase/orders/{id}/approve

审核采购单:通过(待审核 → 已审核)或驳回(→ 草稿);通过时可按开关自动建 ASN 并推送 WMS

POST/api/purchase/orders/{id}/cancel

取消采购单;已下发状态需二次确认并同步取消未开始收货的 WMS 入库单

POST/api/purchase/orders/{id}/release

下发采购单到 WMS(已审核 → 已下发),自动生成 WMS 入库单;幂等,重复下发不会重复建单

GET/api/purchase/orders/{id}/send-email

取采购单邮件的预填模板(收件人/主题/正文/PDF 文件名),供发送前预览编辑

POST/api/purchase/orders/{id}/send-email

把采购单邮件发给供应商(带服务端生成的 PDF 附件),发后记一条邮件事件到时间线

POST/api/purchase/orders/{id}/submit

提交采购单审核(草稿 → 待审核),提交前要求至少有一行明细

POST/api/purchase/orders/batch-release

批量下发多张已审核采购单到 WMS,每单幂等,返回成功与失败明细

到货通知/api/purchase/asnsGETPOSTPATCHDELETE6 个接口

GET/api/purchase/asns

分页查询 ASN(提前发货通知)列表,支持按状态/采购单/货主/单号筛选

POST/api/purchase/asns

从采购单新建 ASN;明细行默认从采购单带出预期数量,也可自定义

DELETE/api/purchase/asns/{id}

删除草稿 ASN(非草稿不能删)

GET/api/purchase/asns/{id}

查 ASN 详情,含明细行和关联的 WMS 入库单

PATCH/api/purchase/asns/{id}

更新 ASN(仅草稿状态可改)

POST/api/purchase/asns/{id}/send

把 ASN 推送到 WMS(草稿 → 已发送),生成或关联 WMS 入库单;同一采购单不会重复建单

Variances/api/purchase/variancesGETPOST2 个接口

GET/api/purchase/variances

分页查询收货差异行(实收与预期不一致的采购单明细行)

POST/api/purchase/variances

确认一条收货差异(或申请补发),记录确认动作和时间

供应商5 个接口

供应商/api/purchase/vendorsGETPOSTPATCHDELETE5 个接口

GET/api/purchase/vendors

供应商列表,可按关键字(编码/名称)和启用状态筛选,按名称排序

POST/api/purchase/vendors

新建供应商;账期归一化校验(prepaid/net30/net60/cod),code 若提供则组织内唯一,不提供自动生成

DELETE/api/purchase/vendors/{id}

停用供应商(软删 is_active=false)

GET/api/purchase/vendors/{id}

供应商详情

PATCH/api/purchase/vendors/{id}

更新供应商(账期归一化校验;改编码时查重)

设置8 个接口

设置/api/purchase/settingsGETPOSTPUTPATCHDELETE6 个接口

GET/api/purchase/settings

取当前组织采购设置(含仓库列表);设置行不存在时返回默认值不落库

PUT/api/purchase/settings

更新采购设置(按组织 upsert)

GET/api/purchase/settings/warehouses

采购仓库列表(默认只取启用的,?all=1 含停用),按 code 排序

POST/api/purchase/settings/warehouses

新建采购仓库,code 在组织内唯一

DELETE/api/purchase/settings/warehouses/{id}

删除采购仓库;已有 PO 引用时拒绝(返回 409,请先停用)

PATCH/api/purchase/settings/warehouses/{id}

更新采购仓库(code 改名查重,address/is_active 可改)

Dashboard/api/purchase/dashboardGET1 个接口

GET/api/purchase/dashboard

采购总览驾驶舱指标:待审核 PO 数、待收货 PO 数、本月采购额、收货差异行数、近期待到货

Context/api/purchase/contextGET1 个接口

GET/api/purchase/context

取采购前端上下文:当前组织的 company_type,用于判断是否为 3PL 版(3PL 版建 PO/ASN 时 merchant 必填)

TMS · 运输管理

运输订单22 个接口

订单/api/tms/ordersGETPOSTPATCHDELETE14 个接口

GET/api/tms/orders

运输订单列表,支持状态、承运商、方式、关键字筛选

POST/api/tms/orders

新建运输订单(草稿,或直接提交为待排线;可选从 WMS 装车单建单)

DELETE/api/tms/orders/{id}

删除运输订单(仅草稿可删)

GET/api/tms/orders/{id}

运单详情:承运商、客户、司机、在途事件、账单行、索赔全聚合

PATCH/api/tms/orders/{id}

编辑运单(仅草稿/待排线可编辑)

POST/api/tms/orders/{id}/assign

指派承运商:待排线运单 → 已派单(可同时指派司机)

DELETE/api/tms/orders/{id}/pod

删除签收记录里的某张照片(按文档 ID 或旧照片 URL)

GET/api/tms/orders/{id}/pod

获取签收记录(照片解析为可下载的签名 URL)

POST/api/tms/orders/{id}/pod

提交签收(JSON 或 FormData 带照片文件;货损会自动把运单转异常)

POST/api/tms/orders/{id}/status

运单状态流转(自动写在途事件;取消时通知已指派司机)

GET/api/tms/orders/{id}/tracking

某运单的在途事件流(按时间正序)

POST/api/tms/orders/{id}/tracking

给运单追加一条在途事件(只追加,不可改)

POST/api/tms/orders/from-wms

接收 WMS 装车单 ready 事件,自动建一条运输订单(幂等)

POST/api/tms/orders/import

批量导入运输订单(草稿):逐行校验,失败行不入库

Tenders/api/tms/tendersGETPOST4 个接口

GET/api/tms/tenders

查某运单的招标记录

POST/api/tms/tenders

向承运商发起招标(仅待排线运单可招标)

POST/api/tms/tenders/{id}/accept

承运商接单:招标变已接受,运单指派该承运商,同单其他招标自动取消

POST/api/tms/tenders/{id}/decline

承运商拒单,可继续向下一家发招标

Stops/api/tms/stopsGETPOSTPATCHDELETE4 个接口

GET/api/tms/stops

查某运单或并单的停靠点列表(按顺序)

POST/api/tms/stops

给运单或并单新增一个停靠点(自动排顺序号)

DELETE/api/tms/stops/{id}

删除停靠点

PATCH/api/tms/stops/{id}

更新停靠点状态(到达/完成自动记时间),可关联 WMS 门店

调度与司机33 个接口

调度/api/tms/dispatchGETPOSTPUTDELETE18 个接口

POST/api/tms/dispatch/assign

手动派单(两步):先预指派拿锁,再正式派单,防重复派单

POST/api/tms/dispatch/auto

一键自动派单:按规则命中候选、金额检查,最高分自动派出去

GET/api/tms/dispatch/board

调度板四列数据:待派单、待确认、执行中、异常

POST/api/tms/dispatch/board

调度板批量操作:设优先级、开/关自动派单

GET/api/tms/dispatch/exceptions

异常中心列表,支持按类型、严重程度、是否已解决筛选

POST/api/tms/dispatch/exceptions

上报一条派单异常(调度板拖拽上报用)

POST/api/tms/dispatch/exceptions/{id}/resolve

处理异常:写解决说明,并真实执行改派/取消/挂起动作

POST/api/tms/dispatch/reassign

改派:取消原派单,重新指派(可指定承运商或自动选)

POST/api/tms/dispatch/recommend

智能推荐承运商:自有车队和外部承运商两栏,按评分排序

DELETE/api/tms/dispatch/rules

停用调度规则(软删,保留审计)

GET/api/tms/dispatch/rules

调度规则列表

POST/api/tms/dispatch/rules

新建调度规则(条件 + 动作策略 + 是否自动派单)

PUT/api/tms/dispatch/rules

完整更新调度规则(body 里带 id)

DELETE/api/tms/dispatch/rules/{id}

停用调度规则(软删,REST 风格)

POST/api/tms/dispatch/rules/{id}

局部更新调度规则(只传要改的字段)

POST/api/tms/dispatch/rules/{id}/priority

规则上移/下移(与相邻规则交换优先级)

POST/api/tms/dispatch/rules/test

规则测试(dry run):不落库,只返回每单的命中评估

GET/api/tms/dispatch/tenders

全租户招标跟踪列表(Dispatch Center 招标面板用)

司机/api/tms/driverGETPOSTPUT12 个接口

GET/api/tms/driver/hos

司机当前 HOS 工时状态和剩余可用工时

POST/api/tms/driver/hos

司机 HOS 打卡:切换工时状态(休息/卧铺/驾驶/值班)

POST/api/tms/driver/issues

司机上报异常(故障/事故/取消/地址错/货损/迟到预警等 7 种)

POST/api/tms/driver/location

司机 GPS 位置上报(高频轻量,upsert 最新位置)

GET/api/tms/driver/messages

司机和调度的双向消息列表(读时把调度来信标为已读)

POST/api/tms/driver/messages

司机回复调度消息

POST/api/tms/driver/pod

司机端 POD 签收提交(multipart,含签名和照片;异常签收自动建索赔草稿)

GET/api/tms/driver/tasks

司机我的任务:待接受和执行中的运单(含打卡进度)

POST/api/tms/driver/tasks/{id}/accept

司机接受或拒绝任务(拒绝会把运单打回待派单池并记异常)

POST/api/tms/driver/tasks/{id}/checkpoint

司机到站打卡:到达装货地/装货完成/到达卸货地/卸货完成(只能顺序向前)

GET/api/tms/driver/voice-settings

读取司机语音播报设置(无记录返回默认值)

PUT/api/tms/driver/voice-settings

写入司机语音播报设置(upsert)

预约/api/tms/appointmentsGETPOSTPATCH3 个接口

GET/api/tms/appointments

查码头预约列表,可按日期和状态筛选

POST/api/tms/appointments

新建一条码头预约(提货或送货)

PATCH/api/tms/appointments/{id}

更新预约信息(状态、司机、车牌、备注)

承运商与费率22 个接口

承运商/api/carriersGETPOSTPATCHDELETE7 个接口

GET/api/carriers

承运商列表(按名称/SCAC/MC号/US DOT 模糊搜,按状态过滤,分页),每条附带其启用的快递服务数量;组织隔离。

POST/api/carriers

新建承运商(名称/运输方式/默认运输方式必填,状态限 ACTIVE/INACTIVE/EXCEPTION);组织隔离。

DELETE/api/carriers/{id}

删除承运商;若该承运商下仍有账号则拒绝删除(409 HAS_ACCOUNTS)

GET/api/carriers/{id}

查询单个承运商详情,并附带其全部快递服务列表

PATCH/api/carriers/{id}

编辑承运商信息(名称/状态/运输方式/联系信息等,按传参局部更新)

GET/api/carriers/{id}/services

查询某承运商的快递服务列表(按 service_code 升序)

POST/api/carriers/{id}/services

给承运商新增快递服务;service_code 在该承运商下必须唯一

承运商/api/tms/carriersGETPOSTPATCH10 个接口

GET/api/tms/carriers

承运商列表,支持关键字、运输方式、启用状态筛选

POST/api/tms/carriers

新建承运商

GET/api/tms/carriers/{id}

承运商详情,含其全部费率

PATCH/api/tms/carriers/{id}

更新承运商信息(含停用)

POST/api/tms/carriers/{id}/invite

邀请承运商开通门户账号,生成邀请链接

GET/api/tms/carriers/{id}/profile

承运商画像:准时率、接单率、单量、异常数、偏好线路、自动分级

POST/api/tms/carriers/{id}/profile/refresh

手动重新计算承运商画像并落库

GET/api/tms/carriers/{id}/rates

某承运商的费率列表

POST/api/tms/carriers/{id}/rates

给承运商新增一条费率

GET/api/tms/carriers/{id}/scorecard

承运商记分卡:准时率、招标接受率、索赔率、总单量、总运费

Dat Rates/api/tms/dat-ratesGETPOSTDELETE5 个接口

DELETE/api/tms/dat-rates

删除 DAT 基准运价:按 ID 批量删,或全部清空

GET/api/tms/dat-rates

DAT 基准运价列表,支持线路、设备类型、日期范围筛选和分页

GET/api/tms/dat-rates/benchmark

基准对比:DAT 市场价 vs 我方承运商报价

GET/api/tms/dat-rates/import

下载 DAT 运价导入的 CSV 模板

POST/api/tms/dat-rates/import

导入 DAT 运价 CSV:先对列映射,支持 dry_run 只校验不写入

结算与索赔15 个接口

账单/api/tms/billsGETPOSTPATCH5 个接口

GET/api/tms/bills

运费账单列表,可按承运商和状态筛选

POST/api/tms/bills

新建运费账单(含按客户分摊的明细行)

GET/api/tms/bills/{id}

账单详情,含明细行、关联订单和客户名称

PATCH/api/tms/bills/{id}

更新账单状态(draft→sent→paid,也可转 disputed 争议)

POST/api/tms/bills/{id}/audit

对账单跑对账:每行金额 vs 运单报价,超容差标争议

索赔/api/tms/claimsGETPOSTPATCH3 个接口

GET/api/tms/claims

索赔列表,可按状态筛选

POST/api/tms/claims

立案一条索赔

PATCH/api/tms/claims/{id}

更新索赔(状态、赔付金额、描述)

Accessorials/api/tms/accessorialsGETPOST2 个接口

GET/api/tms/accessorials

查某个运单或并单的所有附加费(如滞留费、尾板费)

POST/api/tms/accessorials

给运单或并单加一笔附加费

出库单/api/tms/shipmentsGETPOSTPATCH5 个接口

GET/api/tms/shipments

并单列表:本组织全部并单,按创建时间倒序,附承运商名称和成员订单数。

POST/api/tms/shipments

从运输订单创建并单(consolidation):把 ≥2 个待调度/已调度订单合并为一票并单,自动汇总起运地/目的地、总重量/托盘数/件数,并生成并单号。并单成功后成员订单与并单一起流转。

GET/api/tms/shipments/{id}

并单详情:单票并单的完整信息(含承运商 id/名称)以及全部成员订单明细。

PATCH/api/tms/shipments/{id}

更新并单自定义字段(仅 custom_fields;entity=tms_shipment)。merge 语义:incoming 覆盖现有,null 删键,未知历史值保留;非法值 400

POST/api/tms/shipments/{id}/status

并单状态流转:按固定流程推进并单状态,成员订单同步到对应状态(cancelled 除外),并自动写入跟踪事件。允许的流转:planned→dispatched/cancelled;dispatched→picked_up/cancelled;picked_up→in_transit;in_transit→out_for_delivery;out_for_delivery→delivered;delivered→billed;billed 与 cancelled 为终态。

通用14 个接口

Carrier Accounts/api/carrier-accountsGETPOSTPATCH6 个接口

GET/api/carrier-accounts

承运商账号列表(按承运商/是否主账号/客户/关键字过滤,分页),密码永不返回明文、只给是否已配标识;组织隔离。(数据源已统一为 Master Data 承运商账号 shared_carrier_accounts,REQ-20261027-17)

POST/api/carrier-accounts

新建承运商账号(承运商/商户/账号/ API 账号密码必填,密码类字段加密存储);组织隔离。

GET/api/carrier-accounts/{id}

查询承运商账号详情;密码类字段永不返回明文,只返回 has_api_password 是否设置过

PATCH/api/carrier-accounts/{id}

编辑承运商账号;传了密码类字段(api_client_password/api_token/track_api_key/track_api_secret)才覆盖加密存储,不传保留原值

POST/api/carrier-accounts/{id}/ups/ship

用 UPS 账号创建货运并取 shipping label;账号 test_mode 决定走测试环境还是生产环境

POST/api/carrier-accounts/{id}/test

POST /api/carrier-accounts/[id]/test — 承运商账号测试连通(app 站同域代理,转发 integration 单一事实源 /api/integration/carriers/[id]/test;结果写回账号行 last_test_at/last_test_result)

Services/api/carriers/servicesPATCHDELETE2 个接口

DELETE/api/carriers/services/{serviceId}

删除快递服务

PATCH/api/carriers/services/{serviceId}

编辑快递服务(代码/名称/在途天数/启用状态,按传参局部更新)

Export/api/carrier-accounts/exportGET1 个接口

GET/api/carrier-accounts/export

导出承运商账号 CSV 文件(最多 5000 行,密码列永不导出)

Export/api/carriers/exportGET1 个接口

GET/api/carriers/export

按当前筛选条件导出承运商 CSV 文件(最多 5000 行)

计费/api/tms/billingGET1 个接口

GET/api/tms/billing/reconcile

账单对账视图:逐行对比应付账单金额 vs 运单应收报价,标出差异

Dashboard/api/tms/dashboardGET1 个接口

GET/api/tms/dashboard

TMS 运营总览:KPI、待办、状态分布、近 7 天运量、待处理运单

Merchants/api/tms/merchantsGET1 个接口

GET/api/tms/merchants

客户下拉列表(账单分摊用,只返回 id/code/name)

Reports/api/tms/reportsGET1 个接口

GET/api/tms/reports

TMS 标准报表聚合:运量、准时率、成本、异常、应付,一次返回 5 张

YMS · 场站管理

门岗与签到25 个接口

门岗/api/yms/gateGETPOST4 个接口

POST/api/yms/gate/verify

门岗核验 load(REQ-20261025-19 P3;ymsGuard yms.entries view):{token} 扫司机到场 QR/自助核验 QR(令牌组织须与保安组织一致)、{short_code} 自助 6 位短码、{entry_id} 待核验队列点开、{appointment_id} 搜索人工核对——四路回同一核验视图(预约/指派快照/登记行/照片/车牌复核基准/核销窗口状态);动作收口 lib/gate-checkin.ts

POST/api/yms/gate/confirm

门岗确认进场(ymsGuard yms.entries create):{entry_id+token_jti} 链 B 转正或 {token}/{appointment_id} 链 A 核销;服务端复核车牌后 4 位(plate_last4),链 B 条件转正+设备落 dock、链 A 原子翻预约 CHECKED_IN 后建 entry(失败补偿翻回);响应带 Entry Ticket 打印载荷(前端 Device Hub ZPL,失败降级浏览器票面页)

POST/api/yms/gate/reject

门岗拒绝放行(ymsGuard yms.entries edit):reason_code 必选且须在 gate_reject 原因码内(迁移 580 五码);链 B 置 REJECTED、链 A 建 REJECTED entry 留痕(预约不取消);原因进时间线并短信告知司机

Gate Entries/api/yms/gate-entriesGETPOST3 个接口

GET/api/yms/gate-entries

闸口登记时间线(分页,按进出场时间倒序),可按方向/日期/设备号/预约过滤

POST/api/yms/gate-entries

闸口登记车辆进/出场,可核销预约或手工录入

POST/api/yms/gate-entries/{id}/photos

闸口登记拍照上传(REQ-20261023-45):给一条闸口记录追加照片,文件走统一文档中心(ref 挂 gate entry id),照片不回写本行(append-only 触发器禁 UPDATE),GET 列表时反查组装 photos(URL 数组)返回;同字节照片重复上传为幂等成功——文档中心去重命中由 documentsUpload 桥统一处理(原文档挂同一记录时返回原文档、不产生新文档行;挂在别的记录上时复用存储字节另挂一行),不再回 UPLOAD_FAILED(REQ-20261024-08)

入场记录/api/yms/entriesGETPOSTPATCH7 个接口

GET/api/yms/entries

车辆出入登记列表(分页,支持多条件筛选)

POST/api/yms/entries

门岗 Checkin 新建出入登记,可关联预约/收货单/load。一期起:receipt_id/load_id 已被活跃 Entry(CHECKED_IN/WINDOW_CHECKED_IN)绑定时返回 409 `DOC_ALREADY_BOUND`(已出场/已拒绝的历史 Entry 不拦,DB 部分唯一索引兜底);传 client_id 时 customer_name 由服务端按 shared_clients 写名称快照。

GET/api/yms/entries/{id}

取一条出入登记的详情,含操作时间线和关联单据号(预约号/入库单号/装车单号)

PATCH/api/yms/entries/{id}

更新出入登记:普通字段修改 / 拒绝进场(填原因)/ Window 签到(指定月台)

POST/api/yms/entries/{id}/checkout

车辆出场,扫 Ticket 校验码后登记出场

POST/api/yms/entries/{id}/photos

入场登记拍照上传(手机 Entries Check In 用):先建 entry 再逐张上传追加;图片走统一文档中心存档,稳定路径连同 label 以 {url, label} append 进 yms_entries.photos;权限 yms.entries / create(与建单同权);错误走统一六语大白话信封(404 NOT_FOUND / 400 BAD_LABEL·BAD_FILE / 500 UPLOAD_FAILED·SAVE_FAILED);同字节照片重复上传为幂等成功——文档中心去重命中由 documentsUpload 桥统一处理(原文档挂同一 entry 时返回原文档、不产生新文档行;挂在别的记录上时复用存储字节另挂一行),不再回 UPLOAD_FAILED(REQ-20261024-08)

GET/api/yms/entries/{id}/ticket

取闸口 Ticket 打印数据(司机/设备/关联单据/时间),二维码内容就是 ticket_code

Yard Checks/api/yms/yard-checksGETPOSTPATCH11 个接口

GET/api/yms/yard-checks

取盘点任务列表(创建时间倒序),可按状态过滤

POST/api/yms/yard-checks

新建盘点任务(单号 YC-…,初始 planned),全场或按分区盘点。一期扩参:mode(mobile 纸质模式/paper)、count_type(blind 盲盘/open 明盘,默认 blind)、scope_location_types(dock/spot/waiting,范围含月台)、field_checker_id/name(巡场人)

GET/api/yms/yard-checks/{id}

取单个盘点任务的详情(含进度与本单动作流水)。blind 密封(二期):blind 且任务未 completed/applied 时,progress 的差异/待审计数置 0、actions 返回空数组(sighting 产生的 clear_missing 行带设备号,属账面派生状态),completed 后全量返回

PATCH/api/yms/yard-checks/{id}

盘点任务流转:planned→in_progress(记开始时间)→completed;planned/in_progress→cancelled(作废,cancel_reason 必填,手机端无此入口)。一期改写:completed 记 completed_at + close_kind(full 全盘/partial 部分/force 强制,默认 full;force 必带 close_reason_code);result_summary 可空=服务端按差异自动生成(替代旧"必填一句摘要")

GET/api/yms/yard-checks/{id}/results

取盘点任务已提交的车位盘点结果列表。blind 密封(二期):blind 且任务未 completed/applied 时,每行 expected_equipment_id/no 与 diff_status 置 null 返回

POST/api/yms/yard-checks/{id}/results

提交单个车位的盘点结果,系统自动与快照对比出差异状态。blind 密封(二期):blind 且任务未 completed/applied 时,响应不回带比对结果(result 行 expected_*/diff_status 置 null、顶层 diff_status 为 null)

GET/api/yms/yard-checks/{id}/lines

盘点合并视图:开检快照 LEFT JOIN 实盘结果,按走位顺序(yard → zone → 车位号)返回每个位置的派生分类与汇总进度。blind 密封(二期):count_type=blind 且任务未 completed/applied 时,接口层剥离账面——expected_* 置 null、kind 只剩 recorded/skipped/not_entered、is_diff=false、flags 去 fullness_mismatch、progress 的 diffs/pending_review/approved_pending_apply 置 0

POST/api/yms/yard-checks/{id}/review

差异批量审核裁定(任务须 completed):逐行 approve(必带处置+原因码)/ note_only / reject_recheck;默认禁止自审(执行/巡场/录入人不能审本单,组织开关 yms_yard_check_allow_self_review 可放开且留痕);被驳回行自动生成只含争议位的复查单(recheck_of 关联)

POST/api/yms/yard-checks/{id}/apply

过账已批准差异(幂等):位置纠正(投影双写 shared_locations + yms_yard_locations 镜像)/ 无记录柜补登记 / 缺失柜打 missing_since 标记 / 空满不符与损坏只落例外动作不回写;应用前占用冲突硬校验(设备 at_dock/departed、未释放占用、目标位被占 → 该项拦截并回原因);每项写 yms_yard_check_actions 审计行(设备时间线事件源);全部差异处置完毕任务转 applied

POST/api/yms/yard-checks/{id}/photos

Yard Check 损坏拍照上传(二期,手机执行页用):图片走统一文档中心存档,任务须为 in_progress;只存文件不写结果行,照片归属由随后提交的 results.photo_urls 落定;同字节照片重复上传为幂等成功——文档中心去重命中由 documentsUpload 桥统一处理(原文档挂同一任务时返回原文档、不产生新文档行;挂在别的记录上时复用存储字节另挂一行)(REQ-20261024-08)

POST/api/yms/yard-checks/{id}/recognize-no

Yard Check 执行页设备号拍照识别(REQ-20261031-11 件3):照片先走统一文档中心留痕(doc_type=photo、source_system=yms、source_event=yard_check_equipment_ocr、ref_type=yms_yard_check),再经平台内部端点 `POST /api/ai/internal/vision-ocr`(apps/core)识别设备本体印刷/喷涂编号;任务须为 in_progress(不存在 404、非 in_progress 400,文案与 photos 路由同型六语)。识别为空是 200+`candidates:[]`(前端提示手输),识别服务失败才是错误响应(429 OCR_QUOTA / 422 OCR_PARSE_FAILED / 502 OCR_UNAVAILABLE,六语大白话)。幂等:读类生成,不写业务数据,只留痕文档+AI 记账,重复调用重复识别、各自记账。

场站与设备15 个接口

场站/api/yms/yardsGETPOSTPATCHDELETE5 个接口

GET/api/yms/yards

查本组织堆场列表

POST/api/yms/yards

新建堆场,编号在租户内唯一

DELETE/api/yms/yards/{id}

删除堆场,下挂车位时拒绝

GET/api/yms/yards/{id}

查单个堆场详情

PATCH/api/yms/yards/{id}

编辑堆场信息

Yard Locations/api/yms/yard-locationsGETPOST2 个接口

GET/api/yms/yard-locations

取堆场色块图数据:全部车位(含被占用车位的设备信息)+ 容量统计 + 分区列表

POST/api/yms/yard-locations

新建车位:单个创建或批量创建(一次最多 500 个),车位号在堆场内唯一

移动记录/api/yms/movementsGETPOSTPATCH4 个接口

GET/api/yms/movements

移动任务看板,按状态分组

POST/api/yms/movements

新建设备移动任务,任务号 MV-…

GET/api/yms/movements/{id}

取移动任务详情,含设备信息和起止车位信息

PATCH/api/yms/movements/{id}

移动任务状态流转:new→in_progress→picked→closed,异常和强制关闭要填原因

设备/api/yms/equipmentGETPOSTPATCH4 个接口

GET/api/yms/equipment

在场设备查询,附所在车位信息

POST/api/yms/equipment

新建设备档案

PATCH/api/yms/equipment/{id}

编辑设备主数据:待装/待卸标志、承运商、货主、空重状态;状态和车位归属不允许直接改

GET/api/yms/equipment/{id}/history

取设备履历:进出场记录 + 移动任务合并成一条时间线

预约5 个接口

预约/api/yms/appointmentsGETPOSTPATCHDELETE5 个接口

GET/api/yms/appointments

预约列表,附日历分组、准点统计和待卸标志

POST/api/yms/appointments

新建门岗预约,自动生成预约号 AP-…

DELETE/api/yms/appointments/{id}

删除预约,只有 scheduled(已预约)状态的预约才能删

GET/api/yms/appointments/{id}

查单个预约详情及预分配车位信息

PATCH/api/yms/appointments/{id}

预约状态流转(入场/出场/取消)或修改预约字段,仅 scheduled 可改字段

可视化13 个接口

3D 可视化/api/yms/visualizationGETPOSTPATCHDELETE11 个接口

GET/api/yms/visualization/layout

取堆场 3D 布局与箱位占用聚合:箱区统计 + 全部箱位数组 + 闸口车道 + 拖车位置 + 区域多边形

POST/api/yms/visualization/layouts

新建一个 draft 状态的布局版本(布局编辑器保存草稿用)

GET/api/yms/visualization/layouts/{id}/zones

列出某布局版本的所有区域多边形(按排序序号排列)

POST/api/yms/visualization/layouts/{id}/zones

在布局版本上新建一个区域多边形(集装箱区/冷藏区/闸口等)

DELETE/api/yms/visualization/layouts/{id}/zones/{zoneId}

删除布局版本上的一个区域多边形

PATCH/api/yms/visualization/layouts/{id}/zones/{zoneId}

更新区域多边形的名称/顶点/颜色/排序;zone_type 不允许修改

POST/api/yms/visualization/layouts/generate

为堆场自动生成 3D 布局草稿:按 zone 分箱区排箱位,新建 draft 布局版本

POST/api/yms/visualization/layouts/publish

发布布局版本:同堆场旧的 published 版转为 archived,新版成为唯一 published

GET/api/yms/visualization/layouts/versions

取堆场的布局版本列表(draft/published/archived,附每版箱位数)

GET/api/yms/visualization/pick-path

按提箱顺序返回 3D 提箱作业路径点(输入设备编号序列,输出箱位坐标+预计距离)

GET/api/yms/visualization/slot/{id}

取单个箱位明细:3D 信息 + 箱位上堆叠的集装箱 + 相邻箱位(3D 右侧抽屉的数据源)

Dashboard/api/yms/dashboardGET1 个接口

GET/api/yms/dashboard

场站总览指标:月台/车位占用率、待装卸、今日预约、异常、进出流量

任务/api/yms/tasksGET1 个接口

GET/api/yms/tasks/stats

YMS 手机任务页类型过滤计数(REQ-20261031-11 件4):head count 精确计数,条件与两列表端点逐项同源——yard_check=yms_yard_check_tasks+organization_id(mine=1 时 assignee_id=当前用户、无默认状态过滤);movement=yms_movement_tasks+organization_id(mine=1 时 assignee_id=当前用户 OR assignee_id IS NULL,与 movements GET 的 or 条件逐字一致;另加 status 展示集过滤 new/in_progress/picked/exception,与任务页拼平展示集同源,closed/cancelled 不计入,review P2-1 窄修)。列表端点有 limit 上限、badge 用精确 count,超限时数字可不同(定版口径)。

拖柜

拖柜订单41 个接口

订单/api/drayage/ordersGETPOSTPATCHDELETE31 个接口

GET/api/drayage/orders/{id}/documents

订单单证列表(附统一文档的 document_id 和缩略图)

GET/api/drayage/orders/{id}/documents/{docId}/download

门户单证下载:服务端重验全链(订单归属→单证行归属→可见类型/附件归属链)后 302——旧直链行至其 file_url、统一 Documents 行经 portal-bridge 签发 3600s URL;桥不可用 503

GET/api/drayage/orders

拖车订单列表

GET/api/drayage/orders/{id}/appointment-prefill

D47/T16 半自动结构化预填包:按订单组装 fields/containers/missing/sources+深链(租户模板占位全集)+已有 scheduled 预约;?provider_code= 选平台(默认 emodal);599 未应用时提单段降级 bol_model_available=false

POST/api/drayage/orders/{id}/accept

T12/D41 司机确认接单:登录+组织,司机本人服务端按 shared_drivers.user_id 解析(不接受自报);仅派给本人且 status=dispatched 可确认;幂等(条件更新,已确认回 already_accepted=true 同回执、只记一条 driver_accepted 事件);picked_up/delivering 回 implicit=true;非本人 403 NOT_YOUR_ORDER、非待确认 400 NOT_AWAITING_ACCEPT(均人话带下一步)

GET/api/drayage/orders

拖车订单列表

POST/api/drayage/orders

新建拖车订单(草稿),订单号 DRY-…

DELETE/api/drayage/orders/{id}

删除草稿拖车订单(仅草稿可删)

GET/api/drayage/orders/{id}

拖车订单详情,含司机/底盘/货主/地址簿信息

PATCH/api/drayage/orders/{id}

更新草稿/已报价订单字段;派单后仅计费配置(detention_rate)可改

GET/api/drayage/orders/{id}

拖车订单详情,含司机/底盘/货主/地址簿信息

GET/api/drayage/orders/{id}

拖车订单详情,含司机/底盘/货主/地址簿信息

PATCH/api/drayage/orders/{id}

更新草稿/已报价订单字段;派单后仅计费配置(detention_rate)可改

POST/api/drayage/orders/{id}/assign

派单给司机,订单进入 dispatched,司机/底盘置占用

POST/api/drayage/orders/{id}/complete

订单完结(delivering→completed),释放司机/底盘,import 箱送仓库时触发 WMS 生成入库单

DELETE/api/drayage/orders/{id}/documents

删除单证行(手机端重传用),传单证行 row_id,同时软删除底层统一文档

GET/api/drayage/orders/{id}/documents

订单单证列表(附统一文档的 document_id 和缩略图)

POST/api/drayage/orders/{id}/documents

登记订单单证:可传文件直传(multipart,服务端转发统一 Documents API),也可先自传再登记(JSON)

DELETE/api/drayage/orders/{id}/documents/{docId}

删除单证记录,一并软删除底层统一文档(旧行则尝试删桶文件)

GET/api/drayage/orders/{id}/events

订单事件列表(时间倒序,每条附统一文档的附件及缩略图)

POST/api/drayage/orders/{id}/events

记录订单事件,可带文件附件(multipart+files[]);带 client_uuid 时离线重试幂等

GET/api/drayage/orders/{id}/accessorials

附加费清单(605/D40):自动生成的五类费用(预提 prepull_accrued / 超重 overweight_confirmed / 车架分离 chassis_split / 换架 chassis_flip / 堆存 yard_storage_accrued),每行带 evidence(触发事件、时间、证据引用)直读;附 candidates 段(超重许可、未计费换架事件、使用记录派生提示,只展示不计费)。600 未应用时降级按旧列溯源读回并标 `evidence_available=false`。

POST/api/drayage/orders/{id}/accessorials

{action:'confirm_overweight', declared_weight_lbs, weight_source: scale_ticket\

POST/api/drayage/orders/{id}/events

记录订单事件,可带文件附件(multipart+files[]);带 client_uuid 时离线重试幂等

GET/api/drayage/orders/{id}/evidence-pack

**T8/D37 新增**:单柜举证包(只读)——订单/柜信息+双截止日与实际还柜对照(同 assessDualLfd 口径、含预估明示)+事件时间线(订单事件+集装箱不可变事件、正序)+GPS 轨迹点(订单事件打点;司机最新位置单列并标注非历史轨迹)+附件清单(订单单证+事件附件、尽力附 1h 签名 URL)+费用行+warnings(分段降级不整包失败)

POST/api/drayage/orders/{id}/status

订单状态流转,按状态机推进并联动司机/底盘/集装箱跟踪

GET/api/drayage/orders/{id}/timeline

订单全过程时间线(状态/事件/集装箱跟踪/单证/预约合并倒序)

POST/api/drayage/orders/from-wms

WMS 计划出库 load 转拖车订单草稿(按来源幂等)

GET/api/drayage/orders/{id}/charges

GET 订单附加费列表。**D34**:读源由 `DRAYAGE_CHARGES_READ_MODE` 切换(legacy 旧行 / events 计费事件,阶段 B 起 events)

POST/api/drayage/orders/{id}/charges

POST 新增订单附加费。**D34 收口**:charge_code 必须已映射 billing_items(未映射 400 `CHARGE_CODE_NOT_MAPPED` 大白话提示);先写 billing_events(pricing_source=manual+终价快照)后按 `DRAYAGE_CHARGES_WRITE_MODE` 双写旧行(dual 默认)/只写事件(events,阶段 C)/回退旧行(legacy)

DELETE/api/drayage/orders/{id}/charges/{chargeId}

DELETE 附加费。**D34**:双写行先查对应事件,已被月结认领/出账 → 400 `CHARGE_ALREADY_BILLED`;未认领则事件与旧行同删

Do Intake/api/drayage/do-intakeGETPOSTPATCH5 个接口

POST/api/drayage/do-intake

POST /api/drayage/do-intake — 新建队列行 {source, text 或 document_id, file_name}:规则层(+可降级模型层)抽取后进待确认队列,绝不直接建单

GET/api/drayage/do-intake/{id}

GET /api/drayage/do-intake/{id} — 队列行详情(逐字段值/置信度/标记 + 留痕 events)

PATCH/api/drayage/do-intake/{id}

PATCH /api/drayage/do-intake/{id} — 人工修正/补填 {fields, containers, client_id}(终态行 409)

POST/api/drayage/do-intake/{id}/confirm

POST /api/drayage/do-intake/{id}/confirm — 人工确认建单(唯一建单路径;最少信息校验 + 低置信须 reviewed_low_fields + source 幂等键防重复)

POST/api/drayage/do-intake/{id}/actions

POST /api/drayage/do-intake/{id}/actions — {action:'enrich'} 按提单/柜号查 tracks 补全(只填空、缺失明示)/ {action:'reject', reason} 拒绝(原因必填)

Import/api/drayage/importGETPOST5 个接口

POST/api/drayage/import/rates/preview

费率表导入预检:body {headers, rows, mapping?} → 映射建议+置信度+逐行预校验回执(零写库)

POST/api/drayage/import/rates/confirm

费率表导入确认:body {client_id, name, effective_date, currency?, billing_cycle?, rows, mapping, mapping_confirmed} → 新建 billing_rate_sheets 草稿版本+逐行回执+batch_id;同指纹重复 409(failed 批次除外,可重提 supersede)

POST/api/drayage/import/history/preview

历史拖柜单导入预检:同 preview 形态(零写库)

POST/api/drayage/import/history/confirm

历史单导入确认:body {rows, mapping, mapping_confirmed} → 终态只读历史单+提单/柜行落位+逐行回执;坏柜逐行 failed(ISO 6346)不静默;柜行写失败整单回滚不留半成品

GET/api/drayage/import/batches

导入批次列表与逐行回执复查(?kind=rate_sheet\

调度28 个接口

调度/api/drayage/dispatchGETPOSTPATCH12 个接口

GET/api/drayage/dispatch/board

调度看板聚合数据:进行中订单(跟踪富化剩余免费天/海关扣留/船期+紧急度)、司机及当前任务、底盘车

GET/api/drayage/dispatch/empty-return-recommend

GET /api/drayage/dispatch/empty-return-recommend?order_id= — 还空推荐(T11/D43):只基于已维护收空日程+订单还空地/船公司/柜型,返回 status(ok/no_schedule_data/no_matching_window/unavailable)+recommended/alternatives+basis 依据;无日程数据不编造窗口

GET/api/drayage/dispatch/board

调度看板聚合数据:进行中订单(跟踪富化剩余免费天/海关扣留/船期+紧急度)、司机及当前任务、底盘车

GET/api/drayage/dispatch/accept-settings

T12/D41 未确认超时阈值:回 accept_timeout_minutes+source(org/default)+默认/上下限(默认 30 分钟,5–480)

POST/api/drayage/dispatch/accept-settings

T12/D41 设置未确认超时阈值 {accept_timeout_minutes}(整数 5–480,upsert drayage_dispatch_settings);超限回 400 INVALID_TIMEOUT 人话提示

GET/api/drayage/dispatch/live-map

司机实时位置地图数据:在线司机 GPS+当前订单、码头/堆场地址库

GET/api/drayage/dispatch/board

调度看板聚合数据:进行中订单(跟踪富化剩余免费天/海关扣留/船期+紧急度)、司机及当前任务、底盘车

GET/api/drayage/dispatch/live-map

司机实时位置地图数据:在线司机 GPS+当前订单、码头/堆场地址库

GET/api/drayage/dispatch/vehicle-bindings

T20/D51 人车绑定列表(fleet_driver_assignments 单一事实源;当前+近期历史,带车牌/司机名)

POST/api/drayage/dispatch/vehicle-bindings

T20/D51 新建司机—车辆主绑定 {driver_id, vehicle_id};冲突 409 VEHICLE_ALREADY_BOUND/DRIVER_ALREADY_BOUND 明示现有绑定与下一步

PATCH/api/drayage/dispatch/vehicle-bindings

T20/D51 解绑 {assignment_id}(写 unassigned_at 留痕,不删行)

GET/api/drayage/dispatch/recommend

智能推荐派单:按 9 维打分给可用司机排序,双拖/街转机会、TWIC、底盘尺寸匹配加分

司机/api/drayage/driversGETPOSTPATCHDELETE6 个接口

GET/api/drayage/drivers

司机列表,可按状态、启停用筛选、关键字搜索

POST/api/drayage/drivers

新建司机,初始状态 available 且启用

DELETE/api/drayage/drivers/{id}

停用司机(软删,任务中的司机不可停用)

GET/api/drayage/drivers/{id}

司机详情,含当前任务信息

PATCH/api/drayage/drivers/{id}

更新司机信息,可改状态(available/on_job/off_duty)和启停用

GET/api/drayage/drivers/carriers

承运商下拉,供司机主数据表单选择所属承运商(只返回启用的)

预约/api/drayage/appointmentsGETPOSTPATCHDELETE10 个接口

GET/api/drayage/appointments

码头预约列表,可按状态、码头、日期区间筛选

POST/api/drayage/appointments

手工新建一条码头预约,初始状态为 scheduled

DELETE/api/drayage/appointments/{id}

删除一条码头预约

GET/api/drayage/appointments/{id}

码头预约详情,含关联订单的订单号

PATCH/api/drayage/appointments/{id}

更新预约,可改状态(scheduled/completed/cancelled/missed)

POST/api/drayage/appointments/auto-book

按预约平台自动抢号:auto 模式直接落单并回填订单+通知司机,semi_auto 模式返回一键跳转 URL+预填

POST/api/drayage/appointments/confirm

D47/T16 半自动一键回写确认:{provider_code, terminal, appointment_no, window_start, window_end?, gate_no?, container_no?, order_id?, notes?} → 幂等落预约单(同组织+码头+预约号不双落)+回填订单 appointment_at/terminal_appointment_no+写 appointment_booked 事件;612 未应用自动回落+warnings 明示

GET/api/drayage/appointments/providers

码头预约平台列表,内置能力叠加租户自己的配置(未配置时 simulated 默认启用模拟)

POST/api/drayage/appointments/providers

新增或更新租户自己的预约平台配置(按 organization_id+code upsert)

POST/api/drayage/appointments/recommend

按规则推荐可抢时段,避开已有预约冲突,出口单早于截关,按打分排序

跟踪与设备20 个接口

跟踪/api/drayage/trackingGETPOSTPATCHDELETE10 个接口

GET/api/drayage/tracking

集装箱跟踪列表,含剩余免费天数和滞期费用估算

POST/api/drayage/tracking

新建集装箱跟踪(箱号租户内唯一),初始状态在船上

GET/api/drayage/tracking/{id}

集装箱跟踪详情,含事件时间线和关联订单单证

PATCH/api/drayage/tracking/{id}

更新集装箱跟踪字段(最后免费日等);重算滞期风险,超期自动累计每箱每日滞期费

POST/api/drayage/tracking/{id}/events

追加集装箱事件,只追加;按事件代码推进箱状态机,重算滞期风险和剩余免费天

GET/api/drayage/tracking/subscriptions

集装箱自动跟踪订阅列表,可按状态筛选

POST/api/drayage/tracking/subscriptions

新建集装箱跟踪订阅(vizion/terminal49/simulated/shipsgo/timetocargo;无 key 时同步诚实返回未接通、不产模拟数据)

DELETE/api/drayage/tracking/subscriptions/{id}

删除跟踪订阅

PATCH/api/drayage/tracking/subscriptions/{id}

暂停或恢复跟踪订阅

POST/api/drayage/tracking/sync

触发集装箱自动跟踪同步:传箱号同步单箱,不传则同步本租户全部 active 订阅(上限 50)

Empty Return Schedules/api/drayage/empty-return-schedulesGETPOSTPATCHDELETE5 个接口

GET/api/drayage/empty-return-schedules

GET /api/drayage/empty-return-schedules — 码头收空日程列表(码头×船公司×星期×时段;可按 terminal_location_id 筛;含 terminal_name;手工/CSV 维护的运营数据、非实时源)

POST/api/drayage/empty-return-schedules

POST /api/drayage/empty-return-schedules — 新增收空日程行(码头须为地址簿 kind=terminal 地点;weekday 0–6;closes≤opens 表示跨午夜)

PATCH/api/drayage/empty-return-schedules/{id}

PATCH /api/drayage/empty-return-schedules/{id} — 修改收空日程行

DELETE/api/drayage/empty-return-schedules/{id}

DELETE /api/drayage/empty-return-schedules/{id} — 软停用收空日程行(is_active=false)

POST/api/drayage/empty-return-schedules/import

POST /api/drayage/empty-return-schedules/import — CSV 批量导入 {csv}(列:terminal_name,steamship_line,container_size_type,weekday,opens_at,closes_at,effective_from,effective_to,notes;码头名在地址簿解析,逐行回执、坏行不落库)

拖车底盘/api/drayage/chassisGETPOSTPATCHDELETE5 个接口

GET/api/drayage/chassis

底盘车列表,可按状态筛选、关键字搜索(只返回启用的)

POST/api/drayage/chassis

新增底盘车,初始状态为 available

DELETE/api/drayage/chassis/{id}

停用底盘车(软删,使用中不可停用)

GET/api/drayage/chassis/{id}

底盘车详情

PATCH/api/drayage/chassis/{id}

更新底盘车,可改状态(available/in_use/maintenance)

结算与报价21 个接口

发票/api/drayage/invoicesGETPOSTPATCH8 个接口

GET/api/drayage/invoices

账单列表,可按状态和逾期筛选,每条附关联订单、是否逾期、账龄天数

GET/api/drayage/invoices

账单列表,可按状态和逾期筛选,每条附关联订单、是否逾期、账龄天数

POST/api/drayage/invoices

新建账单关联若干订单,关联的已完成订单自动置为 invoiced

GET/api/drayage/invoices/{id}

账单详情,含关联订单(订单号、箱号、报价金额、已开票金额)

POST/api/drayage/invoices

新建账单关联若干订单,关联的已完成订单自动置为 invoiced

GET/api/drayage/invoices/{id}

账单详情,含关联订单(订单号、箱号、报价金额、已开票金额)

PATCH/api/drayage/invoices/{id}

更新账单,可改状态(draft→sent→paid/overdue)及催收状态

GET/api/drayage/invoices/{id}/lines

账单行明细(按趟/按费项的明细行)

报价/api/drayage/quotesGETPOSTPATCHDELETE6 个接口

GET/api/drayage/quotes

报价单列表,accepted 转订单的附带订单号

POST/api/drayage/quotes

新建报价单,总金额 = 基础费率 + 附加费合计

DELETE/api/drayage/quotes/{id}

删除草稿报价单(仅草稿可删)

GET/api/drayage/quotes/{id}

报价单详情

PATCH/api/drayage/quotes/{id}

更新报价单;accepted 时自动生成拖车订单草稿

GET/api/drayage/quotes/rate-lookup

按费率表自动匹配最佳费率(客户专属/箱型/线路/生效期优先级)

Reports/api/drayage/reportsGET7 个接口

GET/api/drayage/reports/profit

Drayage 利润报表汇总(T13/D42):金额只从 billing_events 计费快照派生(经营口径),逐币种总额 + 客户/司机/车辆/场站四维上卷 + Fleet 分摊层 + 覆盖标注;计费快照未应用时 available=false、仅返回件数级事实

GET/api/drayage/reports/profit/orders

Drayage 逐单利润分页(T13/D42):每单一行、逐币种构成,可按客户/司机/车辆/场站筛选

GET/api/drayage/reports/profit/orders/{orderId}

Drayage 逐单费用行下钻(T13/D42):该单期间内全部计费事件逐行,金额来自计费快照、不重算

GET/api/drayage/reports/profit/export

Drayage 利润报表导出(T13/D42):复用 Analytics generateReport 管线生成 csv/xlsx 附件,口径与页面一致;降级时 409

GET/api/drayage/reports/driver-performance

Drayage 司机绩效榜(T14/D44):按司机聚合趟次/柜量/准时率/平均周转/等时/近似工时,全部由订单事件派生(口径见 docs/drayage-driver-performance-design.md §3);期间日期按组织时区日历日切分

GET/api/drayage/reports/driver-performance/orders

Drayage 司机绩效逐单下钻(T14/D44):该司机期间内完成集逐单事实,服务端计算后分页

GET/api/drayage/reports/stage-duration

GET /api/drayage/reports/stage-duration — Drayage 阶段时长统计(T21/D45;?from&to=YYYY-MM-DD 组织时区日历日,缺省本月):提柜/在途/送仓/还空四段时长只从事件时间戳派生(还空时刻 empty_returned 事件优先、订单 return_time 次之),逐段总体(均值/P50/P90/样本数,n<5 抑制)+ 码头/司机/仓库三维 + 五类分类计数公示(缺起点/缺终点/负时长/终点不在期间);候选超 5,000 时 400 PERIOD_TOO_LARGE

通用40 个接口

Bills Of Lading/api/drayage/bills-of-ladingGETPOSTPATCH4 个接口

GET/api/drayage/bills-of-lading

提单列表(筛选 client_id / status / q=提单号模糊,limit≤200+range 分页;599/D33,REQ-20261026-17)

POST/api/drayage/bills-of-lading

按提单批量建单:提单头+containers[]+每柜 order 覆盖/defaults 继承 → 建提单头+N 单+N 柜行;业务键幂等(同 (org, bol_no, bol_type) 复用、逐柜比对已建跳过/新柜追加);货主不一致 400 BOL_CLIENT_MISMATCH 人话报错(D33 §7.1,T6/T19 共用此端点)

GET/api/drayage/bills-of-lading/{id}

按提单汇聚:提单头+柜清单(柜号/箱型/所属订单及状态/track 状态与关键时间)+派生汇总(柜数/已提/已送/已还空),服务端一次查完(D33 §7.2)

PATCH/api/drayage/bills-of-lading/{id}

提单头维护:steamship_line/vessel_voyage/terminal/booking_no/notes/status(关单人工确认)/bol_type 改判(撞唯一键 400 BOL_TYPE_CLASH);client_id 不可改(400 BOL_CLIENT_LOCKED)

Chassis Usage/api/drayage/chassis-usageGETPOSTPATCH4 个接口

GET/api/drayage/chassis-usage

车架使用记录列表(597):筛选 status/pool_id/chassis_id/order_id/from/to,分页 limit/offset(上限 200);每行附 days(使用中实时算)

POST/api/drayage/chassis-usage

人工补录开启使用记录:{chassis_id*, order_id?, container_no?, pool_id?, started_at?, daily_rate?, notes?};同车架已有未结束记录 → 400 CHASSIS_IN_USE(人话说明占用订单)

PATCH/api/drayage/chassis-usage/{id}

修正起止/费率/柜号/备注(已关闭自动重算天数金额);{close:true} 结束并写 AR 计费事件;{void:true} 作废(已入账不可作废)

GET/api/drayage/chassis-usage/pool-summary

池账单差异核对汇总(597):?from&to 按来源池汇总记录数/已结束天数/金额/使用中数,供与池方账单人工核对(不导入池账单)

库位/api/drayage/locationsGETPOSTPATCHDELETE4 个接口

GET/api/drayage/locations

地址簿列表(码头/仓库/客户地址),可按类型筛选

POST/api/drayage/locations

新增地址簿条目

DELETE/api/drayage/locations/{id}

删除地址(软删)

PATCH/api/drayage/locations/{id}

更新地址簿条目

Settlements/api/drayage/settlementsGETPOSTPATCH4 个接口

GET/api/drayage/settlements

司机结算单列表,可按司机和状态筛选(表不存在时返回空列表)

POST/api/drayage/settlements

按司机和周期生成结算单草稿:按趟计费(双拖 1.5×),已进其他结算单的订单自动排除

GET/api/drayage/settlements/{id}

司机结算单详情,含司机信息和按趟重算的明细行

PATCH/api/drayage/settlements/{id}

结算单状态流转:draft→confirmed(确认,可改扣款)→paid(标记已付)

Pairings/api/drayage/pairingsGETPOSTPATCH3 个接口

GET/api/drayage/pairings

双拖/街转配对列表,可按类型和状态筛选(表不存在时返回空列表)

POST/api/drayage/pairings

新建配对建议;传 auto_confirm 可一键确认并触发配对副作用

PATCH/api/drayage/pairings/{id}

配对状态流转:proposed→confirmed(触发副作用)/cancelled,confirmed→completed/cancelled

Voice Alerts/api/drayage/voice-alertsGETPOSTPATCH3 个接口

GET/api/drayage/voice-alerts

待播报的调度员语音告警,按优先级排序(只返回 pending)

POST/api/drayage/voice-alerts

从当前预警扫描生成语音告警(LFD 超期/海关扣留/预约过号/临近截关),24h 内同 ref+type 去重

PATCH/api/drayage/voice-alerts/{id}

标记语音告警已播报或忽略

Chassis Pools/api/drayage/chassis-poolsGETPATCH2 个接口

GET/api/drayage/chassis-pools

车架来源池字典(597):首次读取按组织补齐五码 own/trac/dcli/flexivan/other;含默认日租费率

PATCH/api/drayage/chassis-pools/{id}

维护池字典(名称/默认日租费率/启停);费率只影响之后新开启的记录

Customs/api/drayage/customsPOST2 个接口

POST/api/drayage/customs/inspection-callback

Customs 查验完成回写:查验通过后自动清除集装箱的海关扣留并写事件

POST/api/drayage/customs/link-inspection

手工触发 Customs 查验联动:集装箱标海关扣留后在 Customs App 自动建查验任务单(幂等)

Driver Pay Rates/api/drayage/driver-pay-ratesGETPOST2 个接口

GET/api/drayage/driver-pay-rates

司机单价表列表(按业务类型计趟的单价,表不存在时返回空列表)

POST/api/drayage/driver-pay-rates

新增司机单价,指定业务类型和每趟金额

Rate Tables/api/drayage/rate-tablesGETPOST2 个接口

GET/api/drayage/rate-tables

费率表列表,可按业务类型和启用状态筛选,每条附客户名(表不存在时返回空列表)

POST/api/drayage/rate-tables

新增费率行:客户+业务类型+起止地分区的基准运价及燃油附加、杂费

Voice Settings/api/drayage/voice-settingsGETPOST2 个接口

GET/api/drayage/voice-settings

取司机语音偏好(服务端漫游,无记录返回默认值)

POST/api/drayage/voice-settings

保存司机语音偏好(按 organization_id+driver_id upsert)

Dashboard/api/drayage/dashboardGET1 个接口

GET/api/drayage/dashboard

拖车总览驾驶舱:本月订单、准时率、超期箱、预警、应收、可用司机/底盘

司机/api/drayage/driverPOST1 个接口

POST/api/drayage/driver/location

T3 司机 GPS 上报:body {lat,lng,speed?(km/h),heading?,reported_at?};鉴权登录+组织、driver_id 服务端按 user_id 解析(不接受自报);执行门(名下有 dispatched/picked_up/delivering 在途单才接收,无则 200 {saved:false,reason:'no_active_job'});乱序守卫(reported_at 不新于存量不覆盖,{saved:false,reason:'stale'});upsert 写 drayage_driver_locations(一司机一行)

Dual Transaction/api/drayage/dual-transactionGET1 个接口

GET/api/drayage/dual-transaction/suggestions

双拖配对自动检测:有空箱待还的订单 × 需去码头提重箱的订单,同一码头+箱型一致+时间窗重叠

Merchants/api/drayage/merchantsGET1 个接口

GET/api/drayage/merchants

货主下拉,供建单时选择货主

Optimization/api/drayage/optimizationGET1 个接口

GET/api/drayage/optimization

Dashboard「优化机会」卡:本周可省趟数(双拖+街转各省一次码头进出)及节省的排队时长

Street Turn/api/drayage/street-turnGET1 个接口

GET/api/drayage/street-turn/suggestions

Street Turn 配对建议:进口吉柜(已送达,空箱待还) × 出口空箱需求,含船公司政策检查

Voice Log/api/drayage/voice-logPOST1 个接口

POST/api/drayage/voice-log

写语音播报审计 log,用于排查"司机说没听到"纠纷(90 天 TTL,由定时任务清理)

Wecom Binding`(Portal)/api/drayage/wecom-binding`(portal)POST1 个接口

POST/api/drayage/wecom-binding`(portal)

门户企业微信绑定码签发(T18/D50,窄修 P2-5 补入口):门户已登录会话调用(个人资料页「企业微信绑定」卡),(organization_id, client_id) 只从门户会话派生、请求体无自报项;码只存 SHA-256 哈希(tkt_wecom_binding_codes,迁移 615)、明文只在本次响应回签发人一次,10 分钟有效单次使用,企微会话内赎回;615 未应用回 503 如实降级

LastMile · 最后一公里

调度与路线31 个接口

调度/api/lastmile/dispatchGETPOSTPATCHDELETE8 个接口

POST/api/lastmile/dispatch/auto

按启用的派单规则把待排的配送/取件任务自动指派给司机,可选自动建路线单

GET/api/lastmile/dispatch/overview

调度大屏数据,每位在职司机的最新位置+当日路线进度,以及异常预警列表

POST/api/lastmile/dispatch/reassign

紧急改派,把转出司机路线上的待办站点批量转给另一司机,或摘单回待排池

GET/api/lastmile/dispatch/rules

查询自动派单规则列表,按 priority 升序,可筛选启用/禁用

POST/api/lastmile/dispatch/rules

新建一条自动派单规则(匹配条件 + 分配策略)

DELETE/api/lastmile/dispatch/rules/{id}

删除一条派单规则

GET/api/lastmile/dispatch/rules/{id}

查询单条派单规则的详情

PATCH/api/lastmile/dispatch/rules/{id}

更新派单规则的名称、优先级、启用状态、匹配条件或分配动作

路线/api/lastmile/routesGETPOSTPATCHDELETE8 个接口

GET/api/lastmile/routes

查询路线列表,可按状态、司机、日期筛选,返回路线+司机+站点嵌套数据

POST/api/lastmile/routes

新建一条路线(可嵌套一次性创建多个站点),路线编号自动生成 LMR-000001 起

DELETE/api/lastmile/routes/{id}

删除路线单,挂线的配送单先置空 route_id 并退回 pending,站点级联删除

GET/api/lastmile/routes/{id}

查询单条路线详情,含司机信息和全部站点

PATCH/api/lastmile/routes/{id}

更新路线(换司机、改日期、改状态;状态变更走状态机校验,非法流转会被拒绝)

POST/api/lastmile/routes/{id}/optimize

对单条路线做启发式路径优化(最近邻+时间窗惩罚),回写站点顺序和预计到达时间

PATCH/api/lastmile/routes/{id}/stops

调整站点:批量重排顺序、改单个站点字段、或把站点拖到另一条路线

POST/api/lastmile/routes/{id}/stops

给路线追加站点(自动排到序列尾,支持一次批量加多个)

分仓路由/api/lastmile/routingGETPOSTPATCH7 个接口

POST/api/lastmile/routing/optimize

一键智能排线:把指定日期的待排配送/取件任务按车辆、时间窗、载量自动排成多条路线

GET/api/lastmile/routing/policies

查询排线策略列表,组织无策略时自动播种准时/成本/均衡三条预设

POST/api/lastmile/routing/policies

新建自定义排线策略,可选以某预设为权重基线

PATCH/api/lastmile/routing/policies/{id}

更新排线策略的默认装载口径、HOS 时长、LIFO 模式或设为默认策略

POST/api/lastmile/routing/policies/{id}/preset

对某排线策略应用预设权重(准时/成本/均衡),整体替换 weights,其余字段不动

POST/api/lastmile/routing/replan

基于上一次排线结果做增量重排,处理新单、取消、延误和司机偏离,偏离时以司机当前位置为新起点

GET/api/lastmile/routing/runs/{id}

回放某次排线优化的完整快照,含输入(策略/权重/站点池)和输出(路线/ETA/载量)及未排入站点

Sort/api/lastmile/sortGETPOST8 个接口

POST/api/lastmile/sort/exception

分拣异常件登记,按条码找到配送单或取件单后记一条异常分拣记录(不落格口)

POST/api/lastmile/sort/exceptions/{id}/photos

POST /api/lastmile/sort/exceptions/{id}/photos(multipart:file*)— 给分拣异常记录(lm_sort_records,status=exception)上传照片:走文档中心(ref_type=lm_sort_record),≤10MB、单条最多 5 张;同字节重传幂等(REQ-20261024-08 桥层处理,不产生重复行)。返回 { photo, photos:[{id,url}] }。记录不存在/非异常 → 404 NOT_FOUND;非图片或超限 → 400 BAD_FILE;已满 5 张 → 400 TOO_MANY_PHOTOS;上传失败 → 500 UPLOAD_FAILED

GET/api/lastmile/sort/exceptions/{id}/photos

GET /api/lastmile/sort/exceptions/{id}/photos — 按文档中心 ref 反查该异常记录全部照片 [{id, url(签名链接)}](REQ-20261024-01)

POST/api/lastmile/sort/load

格口装车,把该格口所有未装车的已分拣记录标记装车,格口状态置 closed

GET/api/lastmile/sort/pending

分拣待分拣池,含该 Hub 已取件待分的取件单和未挂路线的待派配送单,已上墙的条码自动排除

POST/api/lastmile/sort/scan

扫码分拣,按条码找单后按路线或区域自动推荐当日 open 格口落格,格口满自动置 full

GET/api/lastmile/sort/slots

查询某 Hub 某日分拣格口列表,含路线、件数、进度和未装车的墙上件/异常件明细

POST/api/lastmile/sort/slots

新建分拣格口,route_id 与 zone 至少其一,格口号在(组织,Hub,日期)下唯一

配送与揽收32 个接口

配送/api/lastmile/deliveriesGETPOSTPATCH9 个接口

GET/api/lastmile/deliveries

查询配送单列表,可按状态、司机、包装单位、任务类型和关键字筛选

POST/api/lastmile/deliveries

新建配送单,单号自动生成 LMD-000001 起,并自动生成客户追踪 token

GET/api/lastmile/deliveries/{id}

查询单张配送单详情,含所属路线和司机信息

PATCH/api/lastmile/deliveries/{id}

更新配送单信息或改状态(状态变更走状态机校验,并自动写一条轨迹事件)

POST/api/lastmile/deliveries/{id}/assign

把配送单派到一条路线(状态 pending/failed → assigned,并写派单轨迹事件)

GET/api/lastmile/deliveries/{id}/events

查询某配送单的轨迹时间线,事件带操作人姓名

POST/api/lastmile/deliveries/{id}/events

给配送单追加一条轨迹事件(event_type 必须是系统允许的枚举值)

POST/api/lastmile/deliveries/{id}/fail

标记配送失败(状态变为 failed,同时在异常中心生成一条待处理异常)

POST/api/lastmile/deliveries/{id}/pod

配送单签收(支持签名/照片/条码/取货码四种签收方式,签收后状态变为 delivered)

揽收/api/lastmile/pickupsGETPOSTPATCH6 个接口

GET/api/lastmile/pickups

查询取件单列表,可按状态、司机筛选、按单号/联系人/地址/电话关键字搜索

POST/api/lastmile/pickups

新建取件单,单号自动取 LMP- 序号

GET/api/lastmile/pickups/{id}

查询取件单详情,含司机和集货点信息

PATCH/api/lastmile/pickups/{id}

更新取件单信息;状态只能直接取消(pending/assigned/failed → cancelled),派单和完成走专用接口

POST/api/lastmile/pickups/{id}/assign

取件单派单,指派司机(可挂路线),状态置 assigned,仅 pending/failed 可派

POST/api/lastmile/pickups/{id}/complete

取件完成或标记失败,支持扫码条码和拍照 URL,失败必须带失败原因

退货/api/lastmile/returnsGETPOSTPATCHDELETE5 个接口

GET/api/lastmile/returns

查询退货单列表,可按状态筛选、按单号/原因/取件地址关键字搜索

POST/api/lastmile/returns

新建退货单(关联原配送单或取件单),可同时自动生成退货取件任务,单号自动取 LRT- 序号

DELETE/api/lastmile/returns/{id}

删除退货单,仅 pending 或 cancelled 状态可删

GET/api/lastmile/returns/{id}

查询退货单详情,含关联的原配送单/取件单

PATCH/api/lastmile/returns/{id}

更新退货单(原因/取件地址/客户),状态按状态机流转:pending→pickup_scheduled→picked_up→received_at_hub→refunded,非终态可取消

司机/api/lastmile/driverGETPOST7 个接口

POST/api/lastmile/driver/cod

司机端代收货款上报,task_id 标识配送单或取件单,实收小于应收拒绝,client_uuid 防离线重发

POST/api/lastmile/driver/exceptions

司机端异常上报,带任务引用时把对应配送/取件单置失败并写轨迹时间线,24 小时内同单同原因去重

POST/api/lastmile/driver/location

司机端上报实时位置(自动关联司机今日进行中的路线,供调度大屏查看)

POST/api/lastmile/driver/location/batch

司机端 GPS 批量上报,写入位置表供调度端实时地图读取,单次最多 500 点

POST/api/lastmile/driver/return-pickups

司机端从配送单/取件单创建退货取回的取件单,自动带上原单地址和联系方式

GET/api/lastmile/driver/tasks

司机端查询当前登录司机今天的任务清单(取件单+配送单合并,按站点顺序排)

POST/api/lastmile/driver/tasks/{id}/status

司机端一键流转任务状态(到达/取件/开始派送/签收/失败),配送单自动写轨迹事件

司机/api/lastmile/driversGETPOSTPATCHDELETE5 个接口

GET/api/lastmile/drivers

查询司机列表,可按状态筛选、按姓名/电话/车牌关键字搜索

POST/api/lastmile/drivers

新建司机档案(主数据在 shared_drivers)

DELETE/api/lastmile/drivers/{id}

停用司机(软删,status 置 inactive)

GET/api/lastmile/drivers/{id}

查询单个司机的详情

PATCH/api/lastmile/drivers/{id}

更新司机信息(姓名/电话/车型/车牌/关联账号/状态)

网点与车辆19 个接口

库区/api/lastmile/zonesGETPOSTPATCHDELETE9 个接口

GET/api/lastmile/zones

查询多边形配送区域 Zone 列表,每条附待复核路线数

POST/api/lastmile/zones

新建多边形配送区域 Zone,boundary 为 GeoJSON Polygon 且必经校验

DELETE/api/lastmile/zones/{id}

停用 Zone(软删,is_active=false),有关联路线/已归区待排单时拒绝

PATCH/api/lastmile/zones/{id}

编辑 Zone(边界顶点/排除区/绑定司机/生效时间),边界实质变更后关联的未执行路线会被标记需复核

POST/api/lastmile/zones/{id}/assign

批量把配送单/取件单归入某 Zone,落在 Zone 排除区内的会被跳过并说明原因

POST/api/lastmile/zones/{id}/optimize

一键排线(异步),为某 Zone 创建排线任务并后台执行,202 返回 job_id 供轮询

POST/api/lastmile/zones/import

GeoJSON FeatureCollection 批量导入 Zone,同名 Zone 会在返回中提示但允许导入

GET/api/lastmile/zones/stop-coords

按 ID 批量查配送单/取件单的坐标,供排线预览编号使用

GET/api/lastmile/zones/unassigned

待归区池,列出未归区且未挂路线的 pending 配送单和取件单

网点/api/lastmile/hubsGETPOSTPATCHDELETE5 个接口

GET/api/lastmile/hubs

查询分拣中心/集货点列表,可按状态筛选、按名称/地址/城市关键字搜索

POST/api/lastmile/hubs

新建分拣中心/集货点(含地址坐标和营业时间)

DELETE/api/lastmile/hubs/{id}

停用 Hub(软删,status 置 inactive)

GET/api/lastmile/hubs/{id}

查询单个 Hub 的详情

PATCH/api/lastmile/hubs/{id}

更新 Hub 信息(名称/地址/城市/坐标/营业时间/状态)

车辆/api/lastmile/vehiclesGETPOSTPATCHDELETE5 个接口

GET/api/lastmile/vehicles

查询车辆列表,可按状态筛选、按车牌关键字搜索,含绑定司机信息

POST/api/lastmile/vehicles

新建车辆档案,plate_no 在组织内唯一

DELETE/api/lastmile/vehicles/{id}

停用车辆(软删,status 置 inactive)

GET/api/lastmile/vehicles/{id}

查询单个车辆的详情,含绑定司机信息

PATCH/api/lastmile/vehicles/{id}

更新车辆信息(车牌/车型/载重载积/托盘数/尾板/绑定司机/状态)

通用12 个接口

Cod/api/lastmile/codGETPOST3 个接口

POST/api/lastmile/cod/collect

代收货款登记(桌面端),delivery_id 与 pickup_id 二选一,实收小于应收直接拒绝

GET/api/lastmile/cod/pending

未交款 COD 记录清单,支持按司机和关键字服务端搜索,返回应收/实收汇总

POST/api/lastmile/cod/settle

COD 交款对账,把选中的收款记录标记为已对账并返回金额汇总

Notify/api/lastmile/notifyPOST3 个接口

POST/api/lastmile/notify

给客户记一条通知记录(模板渲染或直接内容),发送通道暂为 stub,只记 status=sent

POST/api/lastmile/notify/preview

通知模板预览,渲染收件人和文案但不实际发送,只写日志记录

POST/api/lastmile/notify/send

客户通知真实发送,sms 走 Twilio、email 走 Resend,支持模板模式和直接模式,失败也只记日志不抛错

Optimize Jobs/api/lastmile/optimize-jobsGETPOST2 个接口

GET/api/lastmile/optimize-jobs/{job_id}

排线任务状态轮询,running 看进度,done 拿结果,failed 拿错误

POST/api/lastmile/optimize-jobs/{job_id}/confirm

确认排线结果,按引擎结果批量建路线单、站点并指派司机,重复确认幂等返回

Analytics/api/lastmile/analyticsGET1 个接口

GET/api/lastmile/analytics/summary

LastMile 运营分析看板汇总,含今日指标、7/30 天趋势、司机榜单、异常原因和 Zone 时效

客户/api/lastmile/customersGET1 个接口

GET/api/lastmile/customers/track/{token}

客户公开追踪页接口(免登录),凭追踪 token 返回脱敏的包裹进度和事件时间线

Track/api/lastmile/trackGET1 个接口

GET/api/lastmile/track/{token}

公开包裹追踪(免登录),凭 tracking_token 返回配送单状态、ETA 和事件时间线,不含敏感字段

跟踪/api/lastmile/trackingGET1 个接口

GET/api/lastmile/tracking/live

司机实时位置(调度端地图),每司机取当日最新上报点,附当日路线站点进度

RMS · 退货管理

退货21 个接口

退货单/api/rms/rmasGETPOSTPATCH20 个接口

GET/api/rms/rmas

查询退货单(RMA)列表,可按状态、客户、关键字筛选,返回客户名称

POST/api/rms/rmas

新建退货单(RMA),单号自动生成 RMA-000001 起,可一次带上退货明细行

GET/api/rms/rmas/{id}

查询单张退货单详情,含明细行、客户名称和操作人姓名

PATCH/api/rms/rmas/{id}

更新退货单基本信息(已完成/已取消的单不允许修改)

POST/api/rms/rmas/{id}/approve

审批通过退货单(requested → approved),记录审批人和时间

POST/api/rms/rmas/{id}/cancel

取消退货单(仅 requested/authorized/in_transit 状态可取消)

POST/api/rms/rmas/{id}/complete

退货单关单(refunded/exchanged/credited → completed,需先完成财务处理)

POST/api/rms/rmas/{id}/decline

拒绝退货单(requested → declined),拒绝原因必填

POST/api/rms/rmas/{id}/disposition

设置每行的处置决策(回可售/翻新/报废/退供应商/捐赠);回可售的良品会自动推回 WMS 库存

POST/api/rms/rmas/{id}/destroy-confirm

POST /api/rms/rmas/[id]/destroy-confirm — 销毁确认(RMS 二期包 6):body { line_ids[], reviewed_by* };仅 dispose+destroy 行,执行人=当前用户、复核人必填且 ≠ 执行人(双人留痕 destroy_executed/reviewed_by/at),在制转 destroyed 并落 RMS-DESTRUCTION 计费事件

POST/api/rms/rmas/{id}/in-transit

标记退货包裹已寄出、在途中(label_issued → in_transit)

POST/api/rms/rmas/{id}/label-issued

发出退货面单(approved → label_issued),可附面单链接和快递单号

POST/api/rms/rmas/{id}/qc

逐行录入质检结果(A/B/C/D 四级);全部行质检完成后自动进入待处置状态

GET/api/rms/rmas/{id}/qc-photos

查询某 RMA 的质检照片(附 1 小时有效的签名下载地址)

POST/api/rms/rmas/{id}/qc-photos

上传质检照片(multipart 表单),文件走统一文档中心(source_system=rms)

POST/api/rms/rmas/{id}/quarantine

RMA 收货后送隔离待检(状态 received → quarantined),并记状态历史

POST/api/rms/rmas/{id}/receive

退货收货(authorized/in_transit → received):登记各明细行实收数,并生成待质检的在制库存

POST/api/rms/rmas/{id}/resolution

财务处理:登记退款/换货/开信用单的金额和方式(进入对应子状态,再经关单接口完结)

POST/api/rms/rmas/{id}/ship-out

POST /api/rms/rmas/[id]/ship-out — 处置出库确认(RMS 二期包 6):body { line_ids[], carrier, tracking_no, document_id?, notes? };仅 disposal_method=ship_out 的 dispose/rtv/donate 行,写 rms_disposition_shipments + 在制转 shipped_out,rtv 行落 RMS-RTV 计费事件

POST/api/rms/rmas/{id}/start-inspection

开始质检(quarantined → inspecting)

Disposition Shipments/api/rms/disposition-shipmentsPOST1 个接口

POST/api/rms/disposition-shipments

记录处置出库(退货货返给供应商/捐赠/销毁,由 RMS 自己发货),并同步在制库存状态

政策与原因10 个接口

Policies/api/rms/policiesGETPOSTPATCHDELETE5 个接口

GET/api/rms/policies

取退货政策列表(按优先级倒序,附客户名称)

POST/api/rms/policies

新建一条退货政策(退货天数、退货手续费、是否需要发票/原包装、是否自动批准等)

DELETE/api/rms/policies/{id}

删除一条退货政策

PATCH/api/rms/policies/{id}

更新退货政策的任一字段(天数/手续费/开关/优先级/是否启用等)

POST/api/rms/policies/evaluate

评估一笔退货是否符合退货政策:匹配最合适的政策,检查是否在退货窗口期内、是否超金额上限,并算出补货费

原因码/api/rms/reason-codesGETPOSTPATCH3 个接口

GET/api/rms/reason-codes

取三层退货原因码列表(平台预置只读,租户可自定义新增)

POST/api/rms/reason-codes

新建一个三层退货原因码(一级来源 retailer/supplier/customer + 二级 + 编码)

PATCH/api/rms/reason-codes/{id}

更新退货原因码:中英文名称、二级分类、自动批准/拍照开关、默认处置、是否启用、排序

Reasons/api/rms/reasonsGETPOST2 个接口

GET/api/rms/reasons

取退货原因列表(启用中的,预置只读 + 租户自定义)

POST/api/rms/reasons

新增一个自定义退货原因(先保证预置原因存在,再插入)

会计

Accounting59 个接口

计费/api/accounting/billingGETPOSTPUTPATCHDELETE21 个接口

GET/api/accounting/billing/items

3PL 计费收费项目列表,含系统内建项;可按关键字、模块、分类、启用状态筛选

POST/api/accounting/billing/items

新建自定义收费项目(系统内建项不可新增改动)

DELETE/api/accounting/billing/items/{id}

停用收费项目(软删 is_active=false;系统内建项不可停用)

GET/api/accounting/billing/items/{id}

收费项目详情(本组织自定义 + 系统内建均可查)

PUT/api/accounting/billing/items/{id}

编辑收费项目(仅本组织自定义项;系统内建项锁定不可改;code 不可改)

GET/api/accounting/billing/rate-sheets

查 3PL 费率表列表,含每个表的剩余有效天数(负数为已过期)

POST/api/accounting/billing/rate-sheets

新建 3PL 费率表,版本号自动按该客户现有最大版+1,状态为 draft

DELETE/api/accounting/billing/rate-sheets/{id}

删除费率表(仅草稿可删,级联删明细和签署记录)

GET/api/accounting/billing/rate-sheets/{id}

费率表详情,含明细行、签署记录、客户名和距到期天数

PUT/api/accounting/billing/rate-sheets/{id}

更新费率表(生效/归档状态不可编辑;待签署版被改会打回草稿)

GET/api/accounting/billing/rate-sheets/{id}/lines

费率表明细行列表(含收费项目的编码/名称/分类/单位)

POST/api/accounting/billing/rate-sheets/{id}/lines

覆盖式设置费率表明细(先清后插);生效/归档状态拒绝修改,待签署版改明细会打回草稿

POST/api/accounting/billing/rate-sheets/{id}/new-version

基于当前费率表创建新版本(复制表头 + 明细,版本号为同客户最大 +1,新版为草稿)

GET/api/accounting/billing/rate-sheets/{id}/pdf

按需渲染费率表 PDF(未签署为"待签署"预览版,已签署叠加最新签名图片和签署人信息);直接返回 PDF 文件流

POST/api/accounting/billing/rate-sheets/{id}/send

发送费率表给客户签署:草稿变待签署,要求至少有一行明细,并生成 PDF 预览链接

POST/api/accounting/billing/rate-sheets/{id}/sign

客户签署费率表:待签署变生效,同客户其他生效版本自动归档,并记录签署信息

GET/api/accounting/billing/rules

查 3PL 计费规则列表(每个客户一条,指定该客户用哪版费率表)

POST/api/accounting/billing/rules

给一个客户新建 3PL 计费规则(一个客户只能有一条)

DELETE/api/accounting/billing/rules/{id}

停用 Merchant 计费规则(软删 is_active=false)

GET/api/accounting/billing/rules/{id}

Merchant 计费规则详情(绑定的费率表 + 客户名/费率表名一并返回)

PATCH/api/accounting/billing/rules/{id}

编辑 Merchant 计费规则(换绑费率表、改规则设置、启用/停用)

Statements/api/accounting/statementsGETPOSTPATCHDELETE9 个接口

GET/api/accounting/statements

对账单列表(D39/T10):按 client_id / status / q(单号) 筛选,含周期汇总金额与核对状态

POST/api/accounting/statements

生成对账单(draft):按客户+周期从 acc_invoices(汇总应收)/acc_payments(本期已收)/billing_events(逐单明细)派生;期初余额为周期开始时点未收口径(P1-1);同客户同周期同币种已有活单回 409+既有单 id;混币种(仅实际入单发票行判定,P2-1)回 MIXED_CURRENCY;明细行写入失败自动清理并作废单头、可直接重新生成(P2-3)

GET/api/accounting/statements/{id}

对账单详情:头+发票明细快照+逐单费用明细快照+最近核对与差异+发送留痕+aging_reconcile(与现行 ar-aging 口径的对平:合计/期末余额/draft 发票未收额构成说明)

PATCH/api/accounting/statements/{id}

对账单动作(状态机 draft→reviewed→sent/void,服务端拦截):review 审核(approve 须已运行核对;return 退回草稿)、void 作废、resolve_diff 处理差异(resolution=resolved/waived,note 必填留痕)

DELETE/api/accounting/statements/{id}

删除对账单(仅 draft;已审核/已发送须走作废)

POST/api/accounting/statements/{id}/reconcile

运行出账前自动核对:逐行比对已认领应收费用行 vs billing_rate_sheets 合同费率(按事件发生日生效口径+阶梯价);差异类型 NO_CONTRACT_PRICE/PRICE_MISMATCH/QUOTE_SETTLE_DIFF/SNAPSHOT_MISMATCH/ESTIMATED_NOT_SUPERSEDED/DUPLICATE_SUSPECT(仅人工行、同源+同类型+同费目,P2-4)/UNBILLED_IN_PERIOD/STATEMENT_TIE_OUT/STATEMENT_BALANCE_CHECK(期末余额对平差,P1-1);600 快照列未应用时回 409 SNAPSHOT_COLUMNS_MISSING(不假装核对)

GET/api/accounting/statements/{id}/reconcile

最近一次核对运行与差异列表(含 open_diff_count)

POST/api/accounting/statements/{id}/send

真实发送对账单:服务端拦截——状态须 reviewed、最近核对无 open 差异、收件人非空(body.to 优先,缺省客户 contact_email)、降级生成单(detail_degraded)直接拦截须作废重生成(P2-2)、期末余额对平差 balance_check_diff≠0 须已有 STATEMENT_BALANCE_CHECK 差异处理留痕(P1-1);服务端渲染 PDF 经 Resend 发送并记 sent+留痕(acc_statement_sends 成功/失败都记);邮件未配置回 502 EMAIL_NOT_CONFIGURED 且状态不变

GET/api/accounting/statements/{id}/pdf

对账单 PDF(服务端 pdf-lib 渲染,与发送附件同一 builder;汇总+发票明细+逐单费用明细)

账单/api/accounting/billsGETPOSTPATCHDELETE7 个接口

GET/api/accounting/bills

查应付账单列表,可按状态/供应商/关键字筛选,status=open 查全部未付清

POST/api/accounting/bills

新建应付账单,明细行自动算 subtotal/tax/total,账单号 BILL- 全局自动取号

DELETE/api/accounting/bills/{id}

删除账单(仅草稿可删)

GET/api/accounting/bills/{id}

看一张账单的详情,含全部明细行和供应商名

PATCH/api/accounting/bills/{id}

编辑账单:草稿期可改开票日/供应商/币种,其他状态可改备注、到期日和允许的状态流转

GET/api/accounting/bills/{id}/payments

该账单的付款记录(按付款日期倒序)

POST/api/accounting/bills/{id}/payments

给账单登记一笔付款,自动核销并更新已付金额和账单状态

发票/api/accounting/invoicesGETPOSTPATCHDELETE7 个接口

GET/api/accounting/invoices

查应收发票列表,可按状态/客户/关键字筛选,status=open 查全部未收清

POST/api/accounting/invoices

新建应收发票,明细行自动算 subtotal/tax/total,发票号 INV- 全局自动取号

DELETE/api/accounting/invoices/{id}

删除发票(仅草稿可删)

GET/api/accounting/invoices/{id}

看一张发票的详情,含全部明细行和客户名

PATCH/api/accounting/invoices/{id}

改发票;草稿可改全部,已发出只能改备注/到期日/自定义字段/状态流转

GET/api/accounting/invoices/{id}/payments

该发票的收款记录(按收款日期倒序)

POST/api/accounting/invoices/{id}/payments

给发票登记一笔收款,自动核销并更新已收金额和发票状态

Journal/api/accounting/journalGETPOSTPATCHDELETE6 个接口

GET/api/accounting/journal

会计凭证列表,按凭证日期倒序;可按状态、日期区间、编号/备注关键字筛选

POST/api/accounting/journal

新建会计凭证;直接过账(posted)时校验借贷平衡,已关闭的会计期间内不允许建 posted 凭证

DELETE/api/accounting/journal/{id}

删除会计凭证(仅草稿可删)

GET/api/accounting/journal/{id}

会计凭证详情,含分录行及每行的科目编码/名称/类型

PATCH/api/accounting/journal/{id}

编辑会计凭证(仅草稿可改);改分录行是全量替换,并重算借贷总额

POST/api/accounting/journal/{id}/post

草稿凭证过账:校验借贷平衡(至少 2 行分录)、已关闭的会计期间禁止过账

Accounts/api/accounting/accountsGETPOSTPATCHDELETE4 个接口

GET/api/accounting/accounts

取会计科目表列表,按 code 排序,树形返回(顶层 + children);新组织首次打开自动补种默认科目

POST/api/accounting/accounts

新建会计科目,code 在组织内唯一,type 只能是五种标准类型,父科目类型必须一致

DELETE/api/accounting/accounts/{id}

删除科目;有子科目或已被凭证引用时拒绝(可停用代替)

PATCH/api/accounting/accounts/{id}

编辑科目(只能改名称和启用状态,code 不可改)

Reports/api/accounting/reportsGET3 个接口

GET/api/accounting/reports/ar-aging

应收/应付账龄分析,把未结清的发票和账单按逾期天数分桶汇总

GET/api/accounting/reports/balance-sheet

资产负债表(时点):按已过账凭证累计各科目余额,返回资产/负债/权益三类明细、小计和平衡校验

GET/api/accounting/reports/profit-loss

利润表:按已过账凭证在指定区间内汇总收入(贷−借)和费用(借−贷),返回科目明细和小计及净利润

Payments/api/accounting/paymentsGETPOST2 个接口

GET/api/accounting/payments

查收/付款流水列表(对账用),可按方向和关键字筛选

POST/api/accounting/payments

新建独立收/付款记录(不挂账单时用);收款必须指定客户,付款必须指定供应商

CRM · 客户关系

销售管道49 个接口

商机/api/crm/dealsGETPOSTPATCHDELETE13 个接口

GET/api/crm/deals

查商机列表,可按关键字/阶段/公司筛选,附带公司、联系人、负责人信息

POST/api/crm/deals

新建商机,商机号 DL- 自动生成;赢单概率默认取所选阶段的配置

DELETE/api/crm/deals/{id}

删除一个商机

GET/api/crm/deals/{id}

看一条商机的详情,含公司、联系人、客户档案和负责人

PATCH/api/crm/deals/{id}

更新商机;阶段改到 closed_won 会自动把客户转成正式客户档案(幂等)

POST/api/crm/deals/{id}/convert-to-order

把商机一键转成 OMS 销售订单(draft);客户和商品自动匹配/创建,商品行匹配不上会报错

GET/api/crm/deals/{id}/history

查商机的阶段变更历史(倒序,最多 200 条)

GET/api/crm/deals/{id}/line-items

查商机的产品明细行列表

POST/api/crm/deals/{id}/line-items

给商机新增一条产品明细行

DELETE/api/crm/deals/{id}/line-items/{itemId}

删除商机的一条产品明细行

POST/api/crm/deals/{id}/stage

推进商机阶段(带审计记录);推进到 closed_won 自动转成正式客户档案

GET/api/crm/deals/forecast

销售预测:本期在途商机的加权/未加权预测、本期实际赢单、达成率,按负责人分组

GET/api/crm/deals/funnel

销售漏斗统计(供 Kanban 看板用):每阶段的商机数/金额/加权金额、阶段转化率

Deal Stages/api/crm/deal-stagesGETPOSTPATCHDELETE5 个接口

GET/api/crm/deal-stages

查本组织的商机阶段列表(按排序号升序,附带每个阶段的商机数)

POST/api/crm/deal-stages

新建一个商机阶段(stage_key 自动生成,重名 409)

DELETE/api/crm/deal-stages/{id}

删除一个自定义商机阶段(系统阶段、或有商机在用的阶段不许删)

PATCH/api/crm/deal-stages/{id}

更新商机阶段(系统阶段 key 锁定、不可停用)

POST/api/crm/deal-stages/reorder

批量更新商机阶段的排序号

报价/api/crm/quotesGETPOSTPATCHDELETE7 个接口

GET/api/crm/quotes

查报价单列表(分页+关键词+状态过滤,嵌入商机/公司/联系人)

POST/api/crm/quotes

新建报价单(报价单号自动生成,小计/折扣/税/总计服务端自动算)

DELETE/api/crm/quotes/{id}

删除报价单(仅草稿态可删)

GET/api/crm/quotes/{id}

查报价单详情(含明细行)

PATCH/api/crm/quotes/{id}

更新报价单(表头字段、整体换行、状态流转 draft→sent→accepted/rejected/expired)

GET/api/crm/quotes/{id}/pdf

下载报价单 PDF(服务端用 pdfkit 生成)

POST/api/crm/quotes/{id}/send-email

把报价单 PDF 发邮件给客户(成功发送后 draft 状态自动变 sent)

线索/api/crm/leadsGETPOSTPATCHDELETE7 个接口

GET/api/crm/leads

查线索列表,默认按线索评分从高到低排,高分优先跟进

POST/api/crm/leads

新建一条线索,线索号 LD- 自动生成,新建后自动触发工作流和线索评分

DELETE/api/crm/leads/{id}

删除一条线索

GET/api/crm/leads/{id}

看一条线索的详情,含负责人信息

PATCH/api/crm/leads/{id}

更新线索信息;状态只能手动设为 new/contacted/qualified/unqualified,更新后自动重算评分

POST/api/crm/leads/{id}/convert

把线索转成合格客户,同时自动建主联系人和一条初始商机(幂等,已转过直接返回)

POST/api/crm/leads/import

批量导入线索(单次上限 50000 行),支持按邮箱/电话去重(跳过/更新/照导)

Lead Scoring/api/crm/lead-scoringGETPOSTPUT3 个接口

POST/api/crm/lead-scoring/rescore

重新计算本租户全部线索的分数

GET/api/crm/lead-scoring/rules

读本租户的线索评分规则配置

PUT/api/crm/lead-scoring/rules

保存线索评分规则配置(warm 阈值必须小于 hot)

公司/api/crm/companiesGETPOSTPATCHDELETE5 个接口

GET/api/crm/companies

查客户公司列表,可按关键字/启用状态/生命周期阶段筛选,附带关联的客户档案和上级公司

POST/api/crm/companies

新建客户公司档案

DELETE/api/crm/companies/{id}

删除一家公司

GET/api/crm/companies/{id}

查公司详情,嵌入关联商户、商机、母公司和联系人列表

PATCH/api/crm/companies/{id}

更新公司档案

联系人/api/crm/contactsGETPOSTPATCHDELETE5 个接口

GET/api/crm/contacts

查联系人列表,可按关键字或所属公司筛选,附带所属公司信息

POST/api/crm/contacts

新建联系人;同一公司只能有一个主联系人,设为主要自动把旧的降级

DELETE/api/crm/contacts/{id}

删除一个联系人

GET/api/crm/contacts/{id}

查联系人详情,嵌入所属公司

PATCH/api/crm/contacts/{id}

更新联系人

Activities/api/crm/activitiesGETPOSTPATCH4 个接口

GET/api/crm/activities

查跟进活动(电话/邮件/会议/备注/任务)时间线,可按关联对象和类型筛选

POST/api/crm/activities

给线索/商机/联系人/公司记一条跟进活动;记在线索上会自动重算线索评分

GET/api/crm/activities/{id}

查一条跟进活动(call/email/meeting/note/task)的详情

PATCH/api/crm/activities/{id}

更新一条跟进活动(改内容、标记完成、改截止时间)

自动化24 个接口

跟进序列/api/crm/sequencesGETPOSTPATCHDELETE7 个接口

GET/api/crm/sequences

查邮件序列(自动跟进流程)列表,含每序列的加入计数

POST/api/crm/sequences

新建一个邮件自动跟进序列(默认草稿态)

DELETE/api/crm/sequences/{id}

归档一个邮件序列(status=archived,数据保留,不断链)

GET/api/crm/sequences/{id}

查邮件序列详情,含每步的发送/打开/点击统计和当前活跃加入数

PATCH/api/crm/sequences/{id}

更新邮件序列(名称/描述/步骤/自动加入/状态;启用前校验每封邮件步骤都绑了模板)

POST/api/crm/sequences/{id}/enroll

手动把一批线索加入邮件序列(跳过无邮箱/已退订/已在活跃中的)

GET/api/crm/sequences/{id}/enrollments

查某邮件序列的加入记录列表(带线索基本信息)

工作流/api/crm/workflowsGETPOSTPUTDELETE6 个接口

GET/api/crm/workflows

查 CRM 工作流自动规则列表,含每条规则最近一次运行状态

POST/api/crm/workflows

新建一条 CRM 工作流自动规则(触发器+条件+动作)

DELETE/api/crm/workflows/{id}

删除一条工作流规则(执行日志级联删除)

GET/api/crm/workflows/{id}

查一条工作流规则的详情

PUT/api/crm/workflows/{id}

更新一条工作流规则

GET/api/crm/workflows/{id}/runs

查一条工作流规则的执行日志(最近 50 条)

模板/api/crm/templatesGETPOSTPATCHDELETE5 个接口

GET/api/crm/templates

查邮件模板列表(默认只返回启用中的)

POST/api/crm/templates

新建邮件模板(正文支持 {{first_name}} 这类变量占位)

DELETE/api/crm/templates/{id}

停用邮件模板(is_active=false,sequence 里的引用不断链)

GET/api/crm/templates/{id}

查邮件模板详情

PATCH/api/crm/templates/{id}

更新邮件模板

Custom Fields/api/crm/custom-fieldsGETPOSTPUTDELETE6 个接口

GET/api/crm/custom-fields

按实体查自定义字段定义列表(默认只返回生效的,按排序号升序)

POST/api/crm/custom-fields

新建一个自定义字段定义(field_key 由 label 自动生成,创建后不可改)

DELETE/api/crm/custom-fields/{id}

软删除自定义字段定义(is_active=false,记录上已存的历史值保留)

PUT/api/crm/custom-fields/{id}

更新自定义字段定义(field_key/field_type 永不允许改)

GET/api/crm/custom-fields/presets

平台预置扩展字段目录(REQ-20261102-52 B2,D93 §4.3):列 B1 预置常量三项(dpci/item_no=行级 wms_outbound_order_line、return_method=头级 wms_outbound_order,均 text,含六语 label/说明/示例/level)+本组织采纳状态(adopted/definition_id)。登录+组织归属(resolveCrmContext),组织取登录态不接受自报。

POST/api/crm/custom-fields/presets

一键采纳预置:Body `{ preset_key*, lang? }`。在本组织 custom_field_definitions 复制一行(source='platform_preset'、preset_key=键、label 按 lang 取 en/zh 正式名);重复采纳幂等回既有行(already=true,不建重复行,并发撞唯一约束 23505 同样收口);未知 preset_key 返回 400 UNKNOWN_PRESET+大白话 detail。采纳后经 B1 合并层自动出现在本组织模板目录/编辑器扩展字段组。

通用20 个接口

Calls/api/crm/callsGETPOST3 个接口

GET/api/crm/calls

查通话记录列表,可按关联对象过滤

POST/api/crm/calls

一键外呼:经 Twilio 打电话给联系人,并自动记一条通话日志

POST/api/crm/calls/webhook

Twilio 通话状态回调(公开接口,需验签),回写通话最终状态/时长/录音链接

Import/api/crm/importGETPOST3 个接口

POST/api/crm/import/ai-suggest

AI 自动匹配导入列头:把上传文件的前 5 行发给 AI,返回每列→CRM 字段的映射建议

GET/api/crm/import/logs

查导入记录留档:谁、何时、导了多少条

GET/api/crm/import/template

下载标准导入模板(xlsx 文件):列头=字段名(按语言)、必填列标红、附一行示例

Dedupe/api/crm/dedupeGETPOST2 个接口

GET/api/crm/dedupe

扫描重复记录,返回候选重复组(按邮箱/电话/名称匹配)

POST/api/crm/dedupe/merge

把重复记录合并到一条主记录上:关联数据迁移、主记录空字段补齐、被合并记录标记停用

Track/api/crm/trackGET2 个接口

GET/api/crm/track/click/{logId}

邮件点击追踪(公开,无需登录):记录点击后 302 跳转到原链接

GET/api/crm/track/open/{logId}

邮件打开追踪像素(公开,无需登录):返回 1x1 透明 GIF 并记录打开

Unsubscribe/api/crm/unsubscribeGETPOST2 个接口

GET/api/crm/unsubscribe

退订确认页(公开,无需登录):验签通过后展示退订确认表单

POST/api/crm/unsubscribe

确认退订(公开,无需登录):写入退订名单并把该邮箱所有活跃的序列加入置为已退订

Voice Settings/api/crm/voice-settingsGETPUT2 个接口

GET/api/crm/voice-settings

查本租户的语音外呼设置:分钟余额、开关、BYO Twilio 配置(不返回明文密钥)

PUT/api/crm/voice-settings

更新语音外呼设置(语音开关、BYO Twilio 凭证,密钥加密存储)

Dashboard/api/crm/dashboardGET1 个接口

GET/api/crm/dashboard

CRM 仪表盘 KPI:线索/商机汇总、转化率、赢单率

Email Logs/api/crm/email-logsGET1 个接口

GET/api/crm/email-logs

查邮件发送日志列表(sequence 详情/报表用)

Merchants/api/crm/merchantsGET1 个接口

GET/api/crm/merchants

查本组织的商户列表(用于商机页面的商户下拉)

Reports/api/crm/reportsGET1 个接口

GET/api/crm/reports/sales

销售报表:本期赢单/在途/赢单率/平均单价、近 12 个月趋势,按负责人和线索来源分组

Sequence Enrollments/api/crm/sequence-enrollmentsPATCH1 个接口

PATCH/api/crm/sequence-enrollments/{id}

管理一条邮件序列的加入记录:暂停/恢复/手动移出/标记退回

Users/api/crm/usersGET1 个接口

GET/api/crm/users

查本组织的用户列表(用于负责人/指派人下拉)

人事考勤

Attend41 个接口

Groups/api/attend/groupsGETPOSTPUTDELETE7 个接口

GET/api/attend/groups

考勤组列表(附成员数、班次名)

POST/api/attend/groups

新建一个考勤组

DELETE/api/attend/groups/{id}

删除一个考勤组

GET/api/attend/groups/{id}

考勤组详情,含成员列表、班次和挂载的围栏

PUT/api/attend/groups/{id}

更新考勤组(名称/班次/宽限分钟/补卡上限)

DELETE/api/attend/groups/{id}/members

把员工移出考勤组

POST/api/attend/groups/{id}/members

把员工加入考勤组

Geofences/api/attend/geofencesGETPOSTPUTDELETE5 个接口

GET/api/attend/geofences

地理围栏列表(打卡地点范围)

POST/api/attend/geofences

新建一个地理围栏

DELETE/api/attend/geofences/{id}

删除一个地理围栏(同时解除与考勤组的挂载)

GET/api/attend/geofences/{id}

围栏详情,含挂载了该围栏的考勤组

PUT/api/attend/geofences/{id}

更新地理围栏(名称/中心点/半径/关联仓库)

Leave Types/api/attend/leave-typesGETPOSTPUTDELETE5 个接口

GET/api/attend/leave-types

请假类型列表

POST/api/attend/leave-types

新建一个请假类型

DELETE/api/attend/leave-types/{id}

删除一个请假类型

PUT/api/attend/leave-types/{id}

更新请假类型

POST/api/attend/leave-types/seed-defaults

一键写入默认请假类型(幂等,已存在的跳过)

Shifts/api/attend/shiftsGETPOSTPUTDELETE5 个接口

GET/api/attend/shifts

班次列表

POST/api/attend/shifts

新建一个班次

DELETE/api/attend/shifts/{id}

删除一个班次

GET/api/attend/shifts/{id}

班次详情

PUT/api/attend/shifts/{id}

更新班次

Holidays/api/attend/holidaysGETPOSTDELETE3 个接口

GET/api/attend/holidays

节假日历,可按年份查

POST/api/attend/holidays

新增一个节假日

DELETE/api/attend/holidays/{id}

删除一个节假日

Leave Balances/api/attend/leave-balancesGETPOST3 个接口

GET/api/attend/leave-balances

查请假余额(默认今年,附请假类型与员工信息)

POST/api/attend/leave-balances

POST /api/attend/leave-balances — 假期余额发放/调整(HR){ employee_id, leave_type_id, delta_days, reason, year? };余额按天计,正发负调,调后不得为负;写 attend_leave_balance_grants 流水

GET/api/attend/leave-balances/grants

GET /api/attend/leave-balances/grants?employee_id?=&leave_type_id?=&year?=&limit? — 余额发放记录(附员工/类型/发放人信息)

Leave Requests/api/attend/leave-requestsGETPOST3 个接口

GET/api/attend/leave-requests

请假申请列表,可按状态/员工筛选

POST/api/attend/leave-requests

提交请假申请(不填员工则为本人请假)

POST/api/attend/leave-requests/{id}/approve

审批通过一条请假申请(终审会自动扣余额)

Punch Fixes/api/attend/punch-fixesGETPOST3 个接口

GET/api/attend/punch-fixes

补打卡申请列表,可按状态/员工筛选

POST/api/attend/punch-fixes

提交补打卡申请(不填员工则为本人;当月次数受考勤组上限约束)

POST/api/attend/punch-fixes/{id}/approve

通过一条补打卡申请(会自动生成对应的打卡记录)

Approvals/api/attend/approvalsGET1 个接口

GET/api/attend/approvals/pending

统一待办收件箱:待审批的补打卡和请假申请

Daily/api/attend/dailyPOST1 个接口

POST/api/attend/daily/compute

为全组织在职员工计算某天的考勤汇总(迟到/早退/缺勤/请假等)

Dashboard/api/attend/dashboardGET1 个接口

GET/api/attend/dashboard

考勤总览看板:出勤人数、各类 KPI 与异常打卡

My Punches/api/attend/my-punchesGET1 个接口

GET/api/attend/my-punches

当前登录员工自己的打卡记录(默认今天,洛杉矶本地日期)

Punch/api/attend/punchPOST1 个接口

POST/api/attend/punch

打卡:上班/午休出/午休回/下班,支持扫工牌代打和离线补传

Punches/api/attend/punchesGET1 个接口

GET/api/attend/punches

打卡记录管理查询(可按员工/日期范围/异常筛选)

Reports/api/attend/reportsGET1 个接口

GET/api/attend/reports/export

导出月度考勤汇总 CSV(可直接给 payroll 算工资用)

Labor25 个接口

Standards/api/labor/standardsGETPOSTPUT9 个接口

GET/api/labor/standards

工程标准(标准 UPH)列表

PUT/api/labor/standards

维护一条工程标准(标准 UPH):有则更新,无则新增

POST/api/labor/standards

新建离散标准版本行(批三-A / D133 §3.1):按 task_kind 设标准分钟×难度系数,版本沿 effective_from、解析序仓行优先于组织行、同级最新

GET/api/labor/standards/calibration

校准建议:窗口内已审工时按 task_kind×仓聚合(同任务多段先合并、一个完成任务一个样本)算每任务净分钟 P50;样本量低于阈值只回 insufficient_samples、不给数

POST/api/labor/standards/calibration

采纳校准建议落标准行:服务端按同口径重算核对样本量与窗口(不信客户端自报),来源窗口+样本量随行留痕;样本不足回 422 INSUFFICIENT_SAMPLES

GET/api/labor/standards/config

组织级校准配置 { window_days, min_samples }(tenant_settings;无行回定版默认 90/30)

PUT/api/labor/standards/config

更新组织级校准配置(window_days 30–180、min_samples ≥1)

GET/api/labor/standards/caliber

仓级绩效口径(D133 §3.2):?warehouse_id= → { warehouse_id, caliber: uph|standard, changed_by, changed_at }

PUT/api/labor/standards/caliber

切换仓级绩效口径并留痕:仓库行记最近切换人/时,wms_audit_log 记 labor.standard_caliber_change 全史;切到 standard 后该仓 Dashboard/operators 达成率主口径改为对标准效率比,未立标准类型单列不混算

Shifts/api/labor/shiftsGETPOSTPUTDELETE4 个接口

GET/api/labor/shifts

劳动力班次列表,可按仓库筛选

POST/api/labor/shifts

新建一个劳动力班次

DELETE/api/labor/shifts/{id}

删除劳动力班次(软删:is_active 置为 false)

PUT/api/labor/shifts/{id}

更新劳动力班次(名称/时间/仓库/启用停用)

Operators/api/labor/operatorsGET2 个接口

GET/api/labor/operators

操作员列表,附每人今日效率统计

GET/api/labor/operators/{id}

单个操作员的效率详情:分类型统计、日趋势与质量记录

Reconciliation/api/labor/reconciliationGETPOST2 个接口

GET/api/labor/reconciliation

工时三账对账读表(L-G04,REQ-20261101-06):读预计算落表 labor_recon_daily(迁移 744),一人一天一行;等式 paid(考勤日报在钟)=productive 已审+indirect 已审+missing(未解释残差);异常清单按落表生成列 main_rank 全局按严重度排序(R1 置顶),只读落表、不现算两侧原账

POST/api/labor/reconciliation/compute

手动触发对账重算(L-G04,REQ-20261101-06):计算在 DB 函数 labor_recon_run(迁移 744)内完成,幂等可重跑——审核状态变化后重算当日即可,同一输入重算结果一致;与每日定时任务共用同一函数

Job Rates/api/labor/job-ratesGETPOST2 个接口

GET/api/labor/job-rates

GET /api/labor/job-rates — 岗位标准费率(当前有效:每 job_key×范围取今日最新版;+全部版本行+可选 job_key 清单=task_kind 词表+本组织间接类别 code,批三-C REQ-20261108-15 / D133 §3.6 L-G18)

POST/api/labor/job-rates

POST /api/labor/job-rates — 新增岗位费率版本行(job_key×仓可空×每小时费率×币种×生效区间;版本化不改旧行、按作业发生日解析、不回算历史;非词表键须为本组织间接类别 code 或 role: 前缀;写 wms_audit_log labor.job_rate_set 带旧解析值→新值)

Bridge Coverage/api/labor/bridge-coverageGET1 个接口

GET/api/labor/bridge-coverage

GET /api/labor/bridge-coverage — 员工档案↔登录账号桥覆盖(批零 L-G02,REQ-20261108-09,D133 §2.2):{ employees_total, employees_with_user, bridge_fill_rate },与工时对账 coverage 的 bridge_fill_rate 同一定义(全部档案计数、user_id 非空占比);Labor 枢纽页未关联提示条取数

Dashboard/api/labor/dashboardGET1 个接口

GET/api/labor/dashboard

团队生产力总览:平均 UPH、达标率、排行榜和实时动态

Events/api/labor/eventsPOST1 个接口

POST/api/labor/events

记录一条员工效率事件(收货/上架/拣货等作业量)

Indirect Summary/api/labor/indirect-summaryGET1 个接口

GET/api/labor/indirect-summary

direct/indirect 工时占比(L-G15,REQ-20261101-06):只计已结束且 review_status=approved 的条目(与对账等式同口径,pending/rejected 不进占比);direct=非 indirect 任务条目净工时,indirect=带 indirect_code_id 条目净工时(按类别下钻)

Reports/api/labor/reportsGET1 个接口

GET/api/labor/reports

效率报表:按人/事件类型/天汇总,可导出 CSV

Payroll Export/api/labor/payroll-exportGET1 个接口

GET/api/labor/payroll-export

payroll 工时导出(L-G06,REQ-20261101-06):只读对账读模型 labor_recon_daily(迁移 744)按员工×周期聚合,给 ADP/Gusto 等 payroll 系统直接吃数;不自建 payroll。已拒工时不进任何导出口径列(只在对账明细层留痕);paid/indirect/unexplained 三列空值纪律:任一日源值不可用或全周期不适用时整列为空(JSON null / CSV 空格),不出 0 与部分小计

People76 个接口

Reviews/api/people/reviewsGETPOSTPATCHDELETE18 个接口

GET/api/people/reviews

考核列表,可按周期/状态/员工筛选

POST/api/people/reviews

为员工在某个考核周期里创建一条考核记录

GET/api/people/reviews/{id}

考核详情,含周期、员工、主管、目标、面谈记录和权重校验

POST/api/people/reviews/{id}/finalize

结算考核:按目标完成度+上级评分+自评算出最终得分与等级。批一 P-03 验主管(REQ-20261107-53):调用者须为被考核员工的直属主管(现行或考核快照主管)或组织管理员,不符 403 NOT_REVIEW_MANAGER;校验结果落 people_review_audit

POST/api/people/reviews/{id}/manager-review

上级提交对下属的评分和评语。批一 P-03 验主管(REQ-20261107-53):调用者须为被考核员工的直属主管(现行或考核快照主管)或组织管理员,不符 403 NOT_REVIEW_MANAGER;校验结果落 people_review_audit

GET/api/people/reviews/{id}/meetings

某次考核的面谈记录列表(按面谈时间倒序)

POST/api/people/reviews/{id}/meetings

新增一条考核面谈记录

POST/api/people/reviews/{id}/self-review

员工提交自评分数和自评说明。批一 P-03 验本人(REQ-20261107-53):调用者须为被考核员工本人(员工档案绑定的登录账号;未绑定时任何人都不符),不符 403 NOT_REVIEW_SELF;校验结果落 people_review_audit

GET/api/people/reviews/cycles

考核周期列表,可按状态筛选

POST/api/people/reviews/cycles

新建一个考核周期(初始状态为 draft)

GET/api/people/reviews/cycles/{id}

考核周期详情,含考核与目标的数量统计

PATCH/api/people/reviews/cycles/{id}

修改考核周期(名称、评审截止日期、按允许路径流转状态)

GET/api/people/reviews/cycles/{id}/goals

某考核周期内的目标列表,可按员工筛选

POST/api/people/reviews/cycles/{id}/goals

在考核周期内给员工新增一条目标(同员工权重合计不超 100)

GET/api/people/reviews/dashboard

某个考核周期的考核看板(进度、评分分布、平均分、逾期提醒)

DELETE/api/people/reviews/goals/{goalId}

删除一条考核目标

PATCH/api/people/reviews/goals/{goalId}

修改一条考核目标(标题/描述/权重/完成度/状态)

POST/api/people/reviews/goals/{goalId}/agree

主管确认目标:双方对目标达成一致(draft/in_progress → agreed)

Employees/api/people/employeesGETPOSTPATCHDELETE16 个接口

GET/api/people/employees

员工档案列表,支持关键字搜索和按状态/部门筛选

POST/api/people/employees

新建员工档案,工号自动生成

DELETE/api/people/employees/{id}

删除员工档案(返回删除确认)

GET/api/people/employees/{id}

员工档案详情,含主管、下属人数、关联司机和最近 10 条状态变更记录

PATCH/api/people/employees/{id}

修改员工档案(姓名/电话/部门/岗位/主管/证件等;工号不可改,状态走 status 接口)

GET/api/people/employees/{id}/badge

生成该员工的工牌 PDF(A4,可打印)

POST/api/people/employees/{id}/badge-token

生成/轮换员工的打卡二维码 token(旧 token 立即失效)。批一 P-05(REQ-20261107-53):每次生成/轮换补记工牌发行台账 people_badge_issuances(首发 issue / 轮换 rotate,仅记 token 后 4 位)

POST/api/people/employees/{id}/badge-issue

工牌打印发行(批一 P-05 新增):取员工当前有效的打卡二维码载荷;无 token 时生成(不轮换,已有 token 复用),record_print=true 时落 print 发行台账

PATCH/api/people/employees/{id}

修改员工档案(姓名/电话/部门/岗位/主管/证件等;工号不可改,状态走 status 接口)

GET/api/people/employees/{id}/badge

生成该员工的工牌 PDF(A4,可打印)

POST/api/people/employees/{id}/badge-token

生成/轮换员工的打卡二维码 token(旧 token 立即失效)。批一 P-05(REQ-20261107-53):每次生成/轮换补记工牌发行台账 people_badge_issuances(首发 issue / 轮换 rotate,仅记 token 后 4 位)

POST/api/people/employees/{id}/invite

给员工生成一个账号邀请链接(旧的未使用链接自动作废)

POST/api/people/employees/{id}/status

员工状态流转(入职/转正/离职/返聘等),按允许的流转路径校验

POST/api/people/employees/import

员工批量导入预校验:上传 CSV 文本,只校验不写库,返回可导入行与错误行

POST/api/people/employees/import-confirm

员工批量导入确认写入:把预校验通过的行真正建档

GET/api/people/employees/import-template

下载员工批量导入的 CSV 模板(带表头)

Skills/api/people/skillsGETPOSTPUTPATCHDELETE12 个接口

GET/api/people/skills/definitions

本组织的技能定义列表(只看启用中的)

POST/api/people/skills/definitions

新建一条技能定义

PUT/api/people/skills/definitions

为本组织一键写入标准技能定义(幂等,已有不再重复写入)

DELETE/api/people/skills/definitions/{id}

删除一条技能定义

GET/api/people/skills/definitions/{id}

技能定义详情

PATCH/api/people/skills/definitions/{id}

修改技能定义(名称/分类/说明/是否需持证/有效期/启用停用)

DELETE/api/people/skills/employee-skills/{id}

删除员工的一条技能记录

PATCH/api/people/skills/employee-skills/{id}

更新员工的一条技能记录(熟练度/获得日期/到期日/证书编号/备注)

GET/api/people/skills/employees/{employeeId}

某员工的技能列表(含技能定义信息)

POST/api/people/skills/employees/{employeeId}

给员工登记一项技能(同一技能不可重复登记)

GET/api/people/skills/gaps

技能缺口分析:按人数比例算每项技能还差多少人会

GET/api/people/skills/matrix

技能矩阵总览:谁会什么技能,一览表

Onboarding/api/people/onboardingGETPOSTPUTPATCHDELETE9 个接口

GET/api/people/onboarding/tasks

某员工的入职任务清单(附完成进度)

POST/api/people/onboarding/tasks

给员工手动新增一条入职任务

PATCH/api/people/onboarding/tasks/{id}

更新一条入职任务(改状态/标题/负责人/截止日期/备注)

POST/api/people/onboarding/tasks/generate

按启用的入职模板为员工生成入职任务(幂等,已有任务不再重复生成)。批一 P-04(REQ-20261107-53):组织尚无启用模板时先经 ensureOnboardingTemplates 自动播种标准模板(与 PUT /api/people/onboarding/templates 同一实现、幂等),首次使用不再报 NO_TEMPLATES

GET/api/people/onboarding/templates

入职任务模板列表

POST/api/people/onboarding/templates

新建一条入职任务模板

PUT/api/people/onboarding/templates

为本组织一键写入标准入职模板(幂等,已有模板不再重复写入)

DELETE/api/people/onboarding/templates/{id}

删除一条入职任务模板

PATCH/api/people/onboarding/templates/{id}

修改一条入职任务模板

Offboarding/api/people/offboardingGETPOSTPATCH5 个接口

GET/api/people/offboarding

查某员工的离职单(取最新一条)

POST/api/people/offboarding

为员工创建离职单(同一员工未完成的离职单只能有一张)

GET/api/people/offboarding/tasks

某张离职单的离职任务清单(附完成进度)

PATCH/api/people/offboarding/tasks/{id}

更新一条离职任务(改状态/标题/负责人/截止日期/备注)

POST/api/people/offboarding/tasks/generate

按默认模板为离职单生成离职任务(幂等,已有任务不再重复生成)

Departments/api/people/departmentsGETPOSTPATCHDELETE4 个接口

GET/api/people/departments

部门列表,可只看启用的

POST/api/people/departments

新建一个部门

DELETE/api/people/departments/{id}

停用一个部门(软删,数据保留)

PATCH/api/people/departments/{id}

修改部门的名称、编号或启用/停用

Job Titles/api/people/job-titlesGETPOSTPATCHDELETE4 个接口

GET/api/people/job-titles

岗位列表(岗位主数据 shared_job_titles,migration 493),按 sort_order、name 排序;可只看启用的

POST/api/people/job-titles

新建一个岗位(同组织内名称重复返回 409 NAME_EXISTS)

DELETE/api/people/job-titles/{id}

停用一个岗位(软删,数据保留;已引用该岗位的员工与必修要求保留原字符串显示)

PATCH/api/people/job-titles/{id}

修改岗位;改名会级联同步员工档案(shared_employees.job_title)与 Academy 必修要求(academy_position_requirements.job_title)里的岗位字符串,响应附 cascade 计数。若某个 Academy 课程同时挂了旧名与新名两条要求,改名整单拒绝 409 RENAME_CONFLICT(先合并要求再改名);级联中途失败返回 500 CASCADE_FAILED 且已回滚、无半截状态

Data Quality/api/people/data-qualityGETPOST2 个接口

POST/api/people/data-quality/assign-department

批量给还没绑定员工档案的登录账号指定默认部门

GET/api/people/data-quality/unlinked-users

列出还没绑定员工档案的登录账号,方便做数据补齐

Invites/api/people/invitesPOST2 个接口

POST/api/people/invites/accept

校验邀请链接是否有效(公开接口,无需登录),返回员工与组织信息

POST/api/people/invites/link

已登录用户凭邀请 token 把自己的账号绑定到员工档案

Certs/api/people/certsGET1 个接口

GET/api/people/certs/expiring

查未来 N 天内到期的员工证件(如叉车证),到期前提醒换证。批一 P-01(REQ-20261107-53)加法补 expired(已过期证件)与 missing_expiry(未填到期日的证件)两组,响应含 expired{items,total}、missing_expiry{items,total},治「缺失静默计 0」的假绿

司机/api/people/driversPATCH1 个接口

Members/api/people/membersGET1 个接口

GET/api/people/members

本组织在职成员清单,附每人是否已绑定员工档案

Org Chart/api/people/org-chartGET1 个接口

GET/api/people/org-chart

组织架构图数据,含真人员工和 AI 员工

文档中心

Documents40 个接口

Documents/api/documentsGETPOSTPATCHDELETE17 个接口

GET/api/documents

统一文档查询(筛选 + 分页),返回 { items, total, page, page_size };组织隔离。

POST/api/documents

统一文档上传(multipart;支持 client_uuid 幂等键,同组织命中直接返回已有文档 id 不重复存;图片/PDF 上传后自动建 OCR 任务)。

DELETE/api/documents/{id}

软删除文档(进回收站,status='deleted',商户用户不可删)

GET/api/documents/{id}

取文档元数据 + 1 小时有效的下载签名 URL

PATCH/api/documents/{id}

更新文档关联信息(仅 ref_id / ref_type 白名单字段,商户用户不可改)

GET/api/documents/{id}/ask

AI 文档问答的会话列表或某个会话的消息记录

POST/api/documents/{id}/ask

对指定文档提自然语言问题,AI 基于文档 OCR 文本回答并落库问答记录

GET/api/documents/{id}/classification

取文档的 AI 自动分类结果 + 人工修正记录(未分类时 classification 为 null)

PATCH/api/documents/{id}/classification

人工修正文档的 AI 分类结果并追加修正记录(供提示词优化复用)

POST/api/documents/{id}/classify

手动触发 AI 对文档做自动分类 + 关键信息抽取

GET/api/documents/{id}/download

文档字节流式下载(支持服务端水印与预览/下载切换)

DELETE/api/documents/{id}/permanent

彻底删除回收站内的文档(先删存储文件再删 DB 行,分享链接级联删)

POST/api/documents/{id}/restore

从回收站恢复文档(status 置 active、清空 deleted_at,商户用户不可恢复)

GET/api/documents/{id}/share

列出该文档的分享链接

POST/api/documents/{id}/share

为文档新建公开分享链接(可设过期时间/密码,商户用户不可创建)

GET/api/documents/{id}/sign-requests

该文档的签署请求列表(每个带已签/总数)

POST/api/documents/{id}/sign-requests

为文档发起电子签署请求(title + 签署人名单,最多 50 人)

Files/api/documents/filesGETPOSTPATCHDELETE7 个接口

GET/api/documents/files

旧 doc_files 表的文档列表(分页 + 来源应用/客户/类型/任务筛选)

POST/api/documents/files

注册一个文件元数据(新版本用 parent_id 挂链,版本号自动 +1)

DELETE/api/documents/files/{id}

软删除文件(is_active=false)

GET/api/documents/files/{id}

文件详情(含关联客户名)

PATCH/api/documents/files/{id}

更新文件元数据(文件名/客户/任务编号/类型/MIME)

GET/api/documents/files/{id}/versions

文件版本链(从根版本到当前,按 version 升序)

POST/api/documents/files/{id}/versions

基于现有文件创建新版本(自动继承来源/客户/任务信息,version+1)

Sign Requests/api/documents/sign-requestsGETPOST3 个接口

GET/api/documents/sign-requests/{requestId}

签署请求详情(含签署人状态与事件记录,签署人 token 脱敏)

POST/api/documents/sign-requests/{requestId}/finalize

生成最终签署版 PDF(所有签署人签完后叠加签名下载)

POST/api/documents/sign-requests/{requestId}/send

发送签署请求(draft → sent,并记事件)

设置/api/documents/settingsGETPUT2 个接口

GET/api/documents/settings

取本租户文件使用 policy 设置(无则返回默认值)

PUT/api/documents/settings

更新本租户文件使用 policy 设置(白名单校验;配额只读会被忽略)

Audit Logs/api/documents/audit-logsGET1 个接口

GET/api/documents/audit-logs

文档审计日志查询(分页 + 用户/动作/文件名/日期筛选,只追加表)

Batch/api/documents/batchPOST1 个接口

POST/api/documents/batch

文档批量操作:打包 zip 下载 / 软删除 / 批量改文档类型

Ocr Callback/api/documents/ocr-callbackPOST1 个接口

POST/api/documents/ocr-callback

OCR 服务识别完成回调(HMAC-SHA256 验签,回写 documents.ocr_text)

Ocr Dispatch/api/documents/ocr-dispatchPOST1 个接口

POST/api/documents/ocr-dispatch

OCR 任务投递(外部 cron 每 2–5 分钟调用,把 pending 任务推给 OCR 服务)

Quota/api/documents/quotaGET1 个接口

GET/api/documents/quota

本租户文档存储配额查询(总配额 + 已用量,GB)

Shared/api/documents/sharedGET1 个接口

GET/api/documents/shared/{token}

公开分享访问(不鉴权,token 校验 + 过期/密码校验后流式返回文件字节)

Shares/api/documents/sharesDELETE1 个接口

DELETE/api/documents/shares/{shareId}

撤销分享链接(删行,商户用户不可撤销)

Stats/api/documents/statsGET1 个接口

GET/api/documents/stats

文档中心 Dashboard 聚合统计(租户级;总量口径只统计 active 文档,by_status 为全状态)

Trash/api/documents/trashPOST1 个接口

POST/api/documents/trash/purge

回收站到期清理(手动触发,删掉 deleted_at 超过 N 天的文档)

Uploaders/api/documents/uploadersGET1 个接口

GET/api/documents/uploaders

本租户上传过文件的用户列表(去重,供"上传人"筛选下拉用)

系统集成

Integration90 个接口

Edi/api/integration/ediGETPOSTPATCHDELETE20 个接口

GET/api/integration/edi/code-tables

EDI 代码表列表(UPC→SKU 这类查表),支持按名称筛选

POST/api/integration/edi/code-tables

新建 EDI 代码表(version=1),同名 version=1 的已存在会冲突

PATCH/api/integration/edi/code-tables/{id}

更新 EDI 代码表(条目/显示名),每次更新版本号自动 +1

GET/api/integration/edi/connections

EDI 连接列表,只显示注册表内的平台(sps/shopify/ups)

POST/api/integration/edi/connections

新建 EDI 连接,凭证分流加密存储,凭证保存失败会自动回滚连接行

DELETE/api/integration/edi/connections/{id}

删除 EDI 连接,凭证和告警随连接删,mapping 引用置空、传输日志级联删除

PATCH/api/integration/edi/connections/{id}

启停 EDI 连接或改配置,config 是合并式更新不覆盖整包

POST/api/integration/edi/connections/{id}/test

测试 EDI 连接(单据级,不只验认证),顺带校验绑定的 active mapping 样例

GET/api/integration/edi/connectors

EDI 连接器目录(注册表元数据,驱动新建连接向导)

GET/api/integration/edi/field-trees

EDI 字段树,给 Mapper 向导的左右两栏用(源字段/目标字段)

GET/api/integration/edi/mappings

EDI Mapping 列表,支持按连接/单据类型/状态筛选

POST/api/integration/edi/mappings

新建 EDI Mapping 草稿,版本号在同(连接,单据类型,方向)下自动递增

GET/api/integration/edi/mappings/{id}

取单个 EDI Mapping 详情

PATCH/api/integration/edi/mappings/{id}

编辑 Mapping 草稿(名称/定义),只有 draft 状态可编辑,已激活的要新建版本

POST/api/integration/edi/mappings/{id}/activate

激活 Mapping,激活前必须通过四项校验(必填映射/样例测试/代码表/函数库)

POST/api/integration/edi/mappings/{id}/preview

Mapping 样例测试预览(dry-run,不写业务表)

GET/api/integration/edi/templates

预置 EDI Mapping 模板(克隆再改)

GET/api/integration/edi/transmissions

EDI 传输日志列表

POST/api/integration/edi/transmissions/{id}/replay

重放传输(用当前 active mapping 重跑原始 raw),用于改 mapping 或补代码表后重放

POST/api/integration/edi/transmissions/{id}/retry

重试传输(用传输行绑定的原 mapping 重跑原始 raw)

Connections/api/integration/connectionsGETPOSTPUTPATCHDELETE18 个接口

GET/api/integration/connections

渠道连接列表,支持状态/渠道代码/商家/名称模糊筛选

POST/api/integration/connections

新建渠道连接,渠道代码必须在预置目录内。**承运商拒建(REQ-20261105-40)**:channel_code 属承运商/聚合码(fedex/ups/usps/dhl/ontrac、shippo/easypost/shipengine/shipstation/easyship/aftership/sendle/shippingeasy/ordoro)或目录行类目为 carrier/shipping_aggregator 时,回 400 `CARRIER_ACCOUNT_NOT_A_CONNECTION`,detail 带大白话 message 与 manage_at=/master-data/carrier-accounts(指路承运商账号面);向导预检 `POST /api/integration/connections/test` 同口径拒承运商码(承运商凭证测试走账号面独立测试器 carrier-test)

GET/api/integration/connections/{id}

渠道连接详情(单行 + merchant_name + next_sync_at + 注册表 fields + 引用此连接的 flows)

DELETE/api/integration/connections/{id}

删除渠道连接,商品映射级联删除

PATCH/api/integration/connections/{id}

更新渠道连接(名称/状态/同步开关/频率/配置/归属商家)

POST/api/integration/connections/{id}/pull-orders

从渠道拉取订单建单,按渠道单号幂等,未映射 SKU 跳过并记入明细

POST/api/integration/connections/{id}/pull-returns

手动同步退货一轮(退货系统一期;与 Flow 动作 channel.pull_returns / rms.pull_returns 共用同一拉取与入境链):经共享 helper 按注册表工厂取业务 client(零平台分支),按连接水位(integration_pull_cursors)算窗口逐页拉取(每页 ≤200),拉到的退货逐单交入境服务 ingestReturn 落 OMS 退货单;全部无失败才推进水位,有失败水位不动、下轮重拉靠入境幂等(组织+连接+平台单号唯一键)收敛。水位重叠口径:报表型回看 3 天、其余回看 1 个调度周期(按上一轮窗口长度推导)

POST/api/integration/connections/{id}/push-products

把商品推送到渠道 listing(新建或更新),未建渠道映射的记入 skipped

GET/api/integration/connections/{id}/secrets

查看渠道连接凭证 key 列表,只返回 key 名和更新时间,绝不返回明文

PUT/api/integration/connections/{id}/secrets

新增或更新渠道连接凭证(加密存储),value 为空表示删除该 key

POST/api/integration/connections/{id}/sync-inventory

把库存同步推送到渠道(按同步规则),支持真实渠道和模拟推送

POST/api/integration/connections/{id}/test

测试已有渠道连接的真实连通性,无 key 时走模拟并诚实标注

POST/api/integration/connections/test

新建连接向导里的"创建前测试",用临时填的凭证测连通性,不落库

POST/api/integration/connections/{id}/assist

AI 辅助接入开会话并诊断(规则化 v1,不接生成式 AI;设计 docs/connector-ai-assist-design.md §9)。须 body { authorized: true },无授权 400。Perm: `oms.channels` edit。

GET/api/integration/connections/{id}/assist

查该连接最近一条 AI 辅助会话的对客进度(无会话时 data.session=null)。Perm: `oms.channels` view。

POST/api/integration/connections/{id}/assist/retest

用户改完信息后一键重测当前 assist 会话;测通落终态并把连接转 connected。Perm: `oms.channels` edit。

POST/api/integration/connections/{id}/assist/screenshot

发版后批量复测 defect_filed 的 assist 会话(内部任务,x-cron-secret / Bearer CRON_SECRET 鉴权,不对客暴露)。单轮最多 50 条。状态推进=先复测后落终态(verified 时关内部工单+经统一通知中心通知用户);连接缺失落 verify_failed、异常回 defect_filed 可恢复,不悬死中间态。

POST/api/integration/connections/{id}/assist/escalate

POST /api/integration/connections/[id]/assist/escalate — 用户明确要求深查 → 事件桥 assist.escalated(REQ-20261024-58,设计 agent-webhook-bridge §4.2 E1):body { authorized:true } 一次授权;前提已有未终结 assist 会话(工单已落,桥只唤醒不建单),无会话 409;同 trigger 幂等合并,不双唤醒;555 未应用 503 BRIDGE_NOT_READY。Perm: `oms.channels` edit

Flows/api/integration/flowsGETPOSTPATCHDELETE9 个接口

GET/api/integration/flows

流程列表,支持状态/商家筛选,带商家名

POST/api/integration/flows

新建流程(草稿状态,空画布)

DELETE/api/integration/flows/{id}

删除流程,版本和运行记录级联删除

GET/api/integration/flows/{id}

流程详情(扁平结构:流程行 + 当前发布版本 + 版本下拉列表)

PATCH/api/integration/flows/{id}

更新流程(名称/开关/触发器/草稿画布/归属商家),改草稿画布后状态回到 draft

POST/api/integration/flows/{id}/dry-run

全流程试运行(用草稿画布),写动作被拦截、读动作走真实连接器,不写运行记录

POST/api/integration/flows/{id}/publish

发布流程草稿,生成新版本号,流程状态变为已发布

POST/api/integration/flows/{id}/rollback

回滚到历史版本,该版本定义拷回草稿(还需再 publish 才生效)

POST/api/integration/flows/{id}/test-step

单节点试跑,mapper/condition 独立计算,写动作拦截,不写运行记录

承运商/api/integration/carriersGETPOSTPUTPATCHDELETE8 个接口

GET/api/integration/carriers

承运商账号列表(与 OMS 承运商页共用同一张表),支持状态/承运商代码筛选

POST/api/integration/carriers

新建承运商账号,承运商代码必须在预置快递目录内

DELETE/api/integration/carriers/{id}

删除承运商账号,凭证随账号级联删除

GET/api/integration/carriers/{id}

取单个承运商账号详情(含目录名)

PATCH/api/integration/carriers/{id}

更新承运商账号(账号编号/面单模式/状态/启用服务/默认账号)

GET/api/integration/carriers/{id}/secrets

查看承运商凭证 key 列表,只返回 key 名和更新时间,绝不返回明文

PUT/api/integration/carriers/{id}/secrets

新增或更新承运商凭证(加密存储),value 为空表示删除该 key

POST/api/integration/carriers/{id}/test

承运商连通性测试(模拟测试,诚实标注 mock),同时更新账号的上次测试时间

Mappings/api/integration/mappingsGETPOSTPATCHDELETE8 个接口

GET/api/integration/mappings

产品映射列表(渠道 SKU ↔ 内部产品),支持多条件筛选

POST/api/integration/mappings

新建产品映射(渠道 SKU ↔ 内部产品)

POST/api/integration/mappings/bulk-import

POST /api/integration/mappings/bulk-import — 产品映射批量导入(REQ-20261031-50):{dry_run?, rows*: [{connection_name 或 connection_id, external_sku*, product_sku 或 product_id, external_title?, channel_product_id?, is_active?}]};服务端按本组织解析连接名(同名多个回 CONNECTION_AMBIGUOUS)与产品 SKU(wms_items),与既有映射按 (connection_id, external_sku) 唯一键比对出 create/update/skip/error 逐行判定与 reason 码;dry_run=true 只判不写,false 只落 create/update、逐行记结果、部分失败不回滚(23505 竞态转 ALREADY_EXISTS);上限 1000 行(超限 ROW_LIMIT_EXCEEDED);权限 oms.channels create/edit;落库 source='csv_import'

DELETE/api/integration/mappings/{id}

删除一条产品映射

PATCH/api/integration/mappings/{id}

更新产品映射(启用开关/渠道标题/SKU/产品/归属等)

GET/api/integration/mappings/pending

待处理映射占位接口(正式版是拉取渠道未映射商品,当前返回空数组结构)

POST/api/integration/mappings/rematch

POST /api/integration/mappings/rematch {order_no} — 单单重匹配(REQ-20261030-23,设计 D70 §3.3):按当前承运映射表对该单重跑配送翻译,三码(carrier_code/service_code/carrier_mapping_scope)全量回写、未命中清 NULL;订单已进入履约后段(shipped/partial_fulfilled/fulfilled/delivered/cancelled/returned)回 ORDER_LOCKED、无渠道原文回 NO_CHANNEL_RAW;权限 oms.orders edit。

POST/api/integration/mappings/restore

POST /api/integration/mappings/restore {exception_id} — 补映射后恢复(REQ-20261030-23,设计 D70 §3.4):解析异常对应映射(优先 resolved_mapping_id),逐单把挂起行补回订单(仅 draft、(order_id, channel_line_item_id) 判重、金额增量累加);整单未建且 context 带 replay 快照、全行可解析时经内部建单端点整单重放,未全解析回 WAITING_OTHER_SKUS;flow 来源无快照回 FLOW_RERUN 人话提示;结果回写异常 context.last_restore_report;权限 oms.channels edit。

Flow Templates/api/integration/flow-templatesGETPOSTPATCHDELETE6 个接口

GET/api/integration/flow-templates

流程模板列表(官方全部 + 本租户自建)

POST/api/integration/flow-templates

新建租户自己的流程模板,code 自动生成

DELETE/api/integration/flow-templates/{id}

删除租户自建的流程模板(官方模板不许删)

GET/api/integration/flow-templates/{id}

取单个流程模板(官方全局可见,租户只能看自己的)

PATCH/api/integration/flow-templates/{id}

编辑租户自建的流程模板(官方模板只读)

POST/api/integration/flow-templates/{id}/clone

克隆模板成租户自己的(官方模板和自己的模板都能克隆)

Alert Rules/api/integration/alert-rulesGETPOSTPATCHDELETE4 个接口

GET/api/integration/alert-rules

查询告警规则列表,监控流程失败/死信/连接异常

POST/api/integration/alert-rules

新建一条告警规则

DELETE/api/integration/alert-rules/{id}

删除一条告警规则

PATCH/api/integration/alert-rules/{id}

更新告警规则(开关/阈值/通知渠道)

Settings Sync Rules/api/integration/settings-sync-rulesGETPOSTPATCHDELETE4 个接口

GET/api/integration/settings-sync-rules

渠道库存同步规则列表(OMS 设置视角),带仓库和连接信息

POST/api/integration/settings-sync-rules

新建渠道库存同步规则,同一仓库+同一连接只允许一条

DELETE/api/integration/settings-sync-rules/{id}

删除一条渠道库存同步规则

PATCH/api/integration/settings-sync-rules/{id}

编辑渠道库存同步规则(白名单字段)

Inventory Allocation/api/integration/inventory-allocationGETPOSTDELETE3 个接口

GET/api/integration/inventory-allocation

渠道库存分配规则列表,顺带返回渠道目录和已建连接

POST/api/integration/inventory-allocation

保存一条库存分配规则(按组织+渠道代码+SKU upsert)

DELETE/api/integration/inventory-allocation/{id}

删除一条库存分配规则

Catalog/api/integration/catalogGET2 个接口

GET/api/integration/catalog/carriers

预置快递目录(45 家承运商,只读;REQ-20261027-01 起按工作区市场过滤)

GET/api/integration/catalog/channels

预置渠道目录(108 个平台,只返回已上架的连接器,带凭证字段定义;REQ-20261027-01 起带区域视图)

Dead Letters/api/integration/dead-lettersGETPOST2 个接口

GET/api/integration/dead-letters

死信队列,查流程执行失败卡住的消息,支持状态/流程筛选

POST/api/integration/dead-letters/{id}/replay

死信重放,用死信 payload 重跑该流程的已发布版本,死信标记为已重放

Runs/api/integration/runsGET2 个接口

GET/api/integration/runs

流程运行记录列表,带流程名称

GET/api/integration/runs/{id}

单次运行详情,含各节点执行日志

Sync Rules/api/integration/sync-rulesGETPOST2 个接口

GET/api/integration/sync-rules

渠道库存同步规则列表(集成视角),可售量=在手−已分配−安全库存

POST/api/integration/sync-rules

新建渠道库存同步规则

模板/api/integration/templatesGET1 个接口

GET/api/integration/templates

官方流程模板列表(只读,只返回官方模板)

Webhooks/api/integration/webhooksPOST1 个接口

POST/api/integration/webhooks/{code}

外部系统 webhook 入口(无需登录,当前仅支持 shopify),按店铺域名路由到对应租户的已发布流程

Agent Crew

Ai Workforce17 个接口

Agents/api/ai-workforce/agentsGETPOSTPATCHDELETE10 个接口

GET/api/ai-workforce/agents

AI 员工花名册(按租户列出所有 AI 员工)

POST/api/ai-workforce/agents

创建一个 AI 员工(初始状态 draft,直属上级默认创建人)

GET/api/ai-workforce/agents/stats

AI Employee 绩效看板聚合(REQ-20261026-10)——当前自然月的总览指标、逐员工指标与近 8 周趋势(按岗位分组)。鉴权同花名册(租户 Owner/Admin),组织以登录上下文强制;内部 UI 端点,不注册为 agent 工具。指标口径(分子分母/数据源/降级)见 docs/digital-workforce-design.md §23;token 仅组织级(记账表无 agent 维度)。

DELETE/api/ai-workforce/agents/{id}

删除一个 AI 员工

GET/api/ai-workforce/agents/{id}

AI 员工详情,附带知识库、考试记录和拟执行动作

PATCH/api/ai-workforce/agents/{id}

更新 AI 员工信息,状态变更要走合法流转

POST/api/ai-workforce/agents/{id}/exam/start

给 AI 员工开始一次笔试,AI 按题量和语言出题

POST/api/ai-workforce/agents/{id}/exam/submit

交卷阅卷,按答案自动打分并判定是否通过

POST/api/ai-workforce/agents/{id}/knowledge

给 AI 员工上传知识包文档,自动分块存入

POST/api/ai-workforce/agents/{id}/propose

试用期让 AI 员工根据指令拟执行动作(Copilot 模式,先拟好等人确认)

Approvals/api/ai-workforce/approvalsGETPOST4 个接口

GET/api/ai-workforce/approvals

AI 员工拟执行动作的待确认队列(租户批准面数据源)。**REQ-20261027-05 起形状与资格口径变更(以代码为准)**:响应为 `{items}`(旧 `{approvals}` 形状作废);组织成员可进,列表按批准资格过滤——Owner/Admin 全见,非管理员只见自己持有该动作键声明的 approve 动作键(`can_approve` 展开)的动作,无资格整行不可见、载荷不外发;平台域动作(`organization_id` 为空)不进本列表;读到已过期的 `proposed`/`approved` 行惰性置 `expired`。

POST/api/ai-workforce/approvals/{id}/approve

批准一个拟执行的动作(标记 approved,不自动执行;批准后另调 execute 才认领执行)。**REQ-20261027-05 起资格走批准服务层**:Owner/Admin 可审全部;非管理员须持有该动作键声明的 approve 动作键(`can_approve` 实查展开)。涉钱(`payment_change`)动作实行四眼:提出人不可自批(403 `self_approval_forbidden`),组织只有一名有批准资格者时例外放行并在响应带 `warning: "SELF_APPROVAL_SINGLE_APPROVER"`、动作 `audit_note` 留痕。常见错误:404 `action_not_found`、403 `forbidden_not_approver`、400 `action_expired`(已过有效期并置 expired)/ 状态已处理(`action_not_proposed` 口径的人话错误)。

POST/api/ai-workforce/approvals/{id}/reject

驳回一条三档建议动作(REQ-20261027-05 新增;批准页此前已按此契约调用、本期补齐服务端)。资格与 approve 同一把尺(Owner/Admin,或持有该动作键声明的 approve 动作键);仅 `proposed` 可驳,理由落 `decision_reason`+`audit_note`。

POST/api/ai-workforce/approvals/{id}/execute

执行一条已批准的三档动作(REQ-20261027-05 新增;批准页此前已按此契约调用、本期补齐服务端)。资格同 approve/reject。服务层原子认领 `approved`/`failed` → `executing`(`execution_attempts+1`,防并发双执行),认领后按动作键注册表分发执行器。**一期口径(以代码为准)**:注册表 17 键 `executorKey` 全为 `null`,且带 `precondition` 的动作尚无状态核对程序——认领后一律诚实落 `failed` 并回 200(`outcome:'failed'`,`error_code` 为 `PRECONDITION_UNVERIFIABLE`(带前置条件的动作先命中)或 `NO_EXECUTOR`),批准面刷新即可见失败态与人话原因,不假装执行成功;将来某动作解封(注册表填 `executorKey`+执行器登记)后本端点契约不变。

Write Policy/api/ai-workforce/write-policyGETPUT2 个接口

GET/api/ai-workforce/write-policy

读取本组织对平台 Rollie 的写策略(REQ-20261027-05 新增)。组织取服务端会话;Rollie 在服务端按员工号 `AI-000004`+`scope='platform'` 解析(名字不作判定)。无策略行回缺省关形态;策略表未应用(626 未跑)或 Rollie 行未就绪回缺省关+`not_ready:true`,不 500。组织成员可读。

PUT/api/ai-workforce/write-policy

保存本组织对平台 Rollie 的写策略(REQ-20261027-05 新增)。只许组织 Owner/Admin——服务端实查成员角色(`isOrgAdmin`),**不走 `PERMISSIONS_DISABLED` 放行口径**;校验/归一全走纯逻辑:`allowed_tools` 只能是五件候选(`chat_customer_lookup`/`chat_client_lookup`/`chat_item_lookup`/`sales_order_draft_prepare`/`oms_sales_order_draft_create`)的子集,建单工具不在清单时其余四件归一清空;每次保存写一条管理员审计(`platform_admin_audit_logs`,action=`rollie_write_policy_update`)。

Audit/api/ai-workforce/auditGET1 个接口

GET/api/ai-workforce/audit

本组织 AI 工具调用审计查询(租户 Admin 面,REQ-20261027-05 新增)。组织只取服务端会话并强制 `eq` 过滤(query 里带 `organization_id` 也不认,跨组织行在查询层即不可见);服务端 `count exact`+`.range()` 分页,禁全量拉取;只回脱敏摘要白名单字段(`gate_results`/`payload_hash` 等内部字段不查不回,只留 ops 面);建单成功行按(本组织+单号)批量解析 `order_id` 供页面拼 OMS 深链(解析不到不带)。审计表未应用(603/624 未跑)回空列表+`not_ready:true`,不 500。

Mygpt18 个接口

Topics/api/mygpt/topicsGETPOSTPATCHDELETE7 个接口

GET/api/mygpt/topics

当前用户的 MyGPT 对话列表(按 updated_at 倒序)

POST/api/mygpt/topics

新建一个 MyGPT 对话

DELETE/api/mygpt/topics/{id}

删除一个对话

GET/api/mygpt/topics/{id}

对话详情,附全量消息和附件

PATCH/api/mygpt/topics/{id}

重命名对话标题

GET/api/mygpt/topics/{id}/messages

对话的消息列表(分页)

POST/api/mygpt/topics/{id}/messages

在对话里发一条消息,AI 回复并记入对话

Scheduled Tasks/api/mygpt/scheduled-tasksGETPOSTPATCHDELETE6 个接口

GET/api/mygpt/scheduled-tasks

当前用户的 MyGPT 定时任务列表(每条附最新一次运行)

POST/api/mygpt/scheduled-tasks

新建 MyGPT 定时任务

DELETE/api/mygpt/scheduled-tasks/{id}

删除一个定时任务

GET/api/mygpt/scheduled-tasks/{id}

定时任务详情(附最新 5 次运行)

PATCH/api/mygpt/scheduled-tasks/{id}

更新定时任务(改 schedule 会重新计算下次运行)

GET/api/mygpt/scheduled-tasks/{id}/runs

定时任务的执行历史(分页,started_at 倒序)

Files/api/mygpt/filesGETPOST2 个接口

GET/api/mygpt/files

某对话的附件列表

POST/api/mygpt/files

给对话上传附件(multipart 表单)

Chat/api/mygpt/chatPOST1 个接口

POST/api/mygpt/chat

MyGPT 核心对话引擎,单轮问答(不写对话库)

Feedback/api/mygpt/feedbackPOST1 个接口

POST/api/mygpt/feedback

给 MyGPT 回答点反馈表情(学 Claude),sad 时可附原因

Reports/api/mygpt/reportsPOST1 个接口

POST/api/mygpt/reports

MyGPT 报表导出,按列和行数据生成文件(csv/md/xlsx/docx/pdf)

平台通用

2 个接口

/(912 两表 updated_at 口径,W5 登记/REVIEW-W4 NIT-7①)注—2 个接口

注(912 两表 updated_at 口径,W5 登记/REVIEW-W4 NIT-7①)

migration 912 的 `ai_teaching_submissions`/`ai_custom_requests` 两表 `updated_at` **无 DB 触发器维护**(与 910 既有风格一致):训练进度页「最近更新」取该列,故平台侧(ops 工单流)回写状态/判层结论时**必须自觉 bump `updated_at=now()`**,漏 bump 会让租户侧看到旧更新时间。ops 工单流落地时按此对齐

—(无新端点)3D Pack 智能打包推荐(2026-10-24,REQ-20261023-36)

**纯客户端计算、无专用服务端端点**:发货台页面用已加载的订单行(`resolve` 返回)与包装材料(`GET /api/wms/items?item_type=material`)调 `@docklify/lib/quick-pack` 适配层 + `container-loading/packer` 在浏览器内逐材料试算选优;弹窗 Apply 只写页面包裹状态,落库走既有确认发货路径。覆盖率审计时勿按「缺端点」判缺口。设计:`docs/quick-pack-design.md`。

`Sourcing.Pull Order Status`1 个接口

`Sourcing.Verify Availability/Flow 动作 `sourcing.create_order` / `sourcing.pull_order_status` / `sourcing.verify_availability—1 个接口

—Flow 动作 `sourcing.create_order` / `sourcing.pull_order_status` / `sourcing.verify_availability

Integration 执行器动作(双 executor 接线、WRITE_ACTIONS 登记,无独立 HTTP 路由):create_order 以 po_id 提交或 order_id 评估建单、pull_order_status 走单连接同步、verify_availability 走 PO 复检;全部经底座编排同一事实源

Academy28 个接口

Courses/api/academy/coursesGETPOSTPATCHDELETE8 个接口

GET/api/academy/courses

课程列表(按所属系统/难度/发布状态/关键词筛选,分页)

POST/api/academy/courses

新建课程(编号组织内唯一)

DELETE/api/academy/courses/{id}

删除课程(内容节级联删;已有选课记录则拒绝)

GET/api/academy/courses/{id}

课程详情(含按 sort_order 排好的内容节)

PATCH/api/academy/courses/{id}

更新课程(标题/描述/系统/难度/封面/发布状态)

POST/api/academy/courses/{id}/exam/generate

为课程 AI 生成一套考题(同课程+语言 24h 内复用缓存;考生只拿去答案题面)

POST/api/academy/courses/{id}/exam/submit

交卷阅卷(单选/判断自动判、简答 AI 语义判分;80 分通过自动颁发证书)

POST/api/academy/courses/generate-test

AI 生成测试课程(快速填充测试数据,编号 TEST- 前缀、直接发布)

Categories/api/academy/categoriesGETPOSTPATCH4 个接口

GET/api/academy/categories

GET /api/academy/categories — 两级分类树(逐节点课程计数;nonempty=true 只回有已发布课节点)。权限:登录+组织归属(REQ-20261101-13)

POST/api/academy/categories

POST /api/academy/categories — 新建分类节点(平台统一维护,仅 platform_staff;两级写死)。权限:平台运营

PATCH/api/academy/categories/{id}

PATCH /api/academy/categories/[id] — 改名/排序/停用启用(带课节点拒绝停用)。权限:平台运营

POST/api/academy/categories/{id}/merge

POST /api/academy/categories/[id]/merge — 分类归并(同级;一级连子节点整体改挂;源停用;会改变课程 system 镜像时拒绝;执行段为单事务 RPC academy_apply_merge,改挂+停用+审计同事务。分类 code 平台内全局唯一,无同名冲突分支)。权限:平台运营

Position Requirements/api/academy/position-requirementsGETPOSTDELETE4 个接口

DELETE/api/academy/position-requirements

删除岗位-课程必修要求

GET/api/academy/position-requirements

岗位要求列表(按岗位名/课程筛选)

POST/api/academy/position-requirements

新增岗位-课程必修要求(岗位名按文本匹配员工岗)

GET/api/academy/position-requirements/check

查某员工岗位必修课达标状态(达标/逾期/在学/未开始)

Tags/api/academy/tagsGETPOSTPATCH3 个接口

GET/api/academy/tags

GET /api/academy/tags — 标签列表(kind=role/topic/level_hint;平台预置+本组织)。权限:登录+组织归属

POST/api/academy/tags

POST /api/academy/tags — 新建标签(role 仅平台预置;topic 平台或本组织)。权限:平台标签限平台运营

PATCH/api/academy/tags/{id}

PATCH /api/academy/tags/[id] — 标签改名/排序/停用启用。权限:平台标签限平台运营、本组织标签按归属

Enrollments/api/academy/enrollmentsGETPOSTPATCH3 个接口

GET/api/academy/enrollments

我的课程(当前登录用户绑定的员工;query 可查他人、按状态筛选)

POST/api/academy/enrollments

选课(默认给自己选;管理员可代他人选)

PATCH/api/academy/enrollments/{id}/progress

更新学习进度(首次学习变在学中;100% 结业并自动颁发证书 + People 技能 badge)

Admin/api/academy/adminGET2 个接口

GET/api/academy/admin/overdue

逾期未达标名单(岗位必修课逾期还没拿证的员工,按逾期天数倒序)

GET/api/academy/admin/stats

团队学习统计(学员数/结业率/考试通过率/发证数)

My/api/academy/myGET2 个接口

GET/api/academy/my/path

GET /api/academy/my/path — 我的学习路径(按本人岗位必修聚合、按一级分类分组、附进度与角色标签)。权限:登录+组织归属

GET/api/academy/my/points

GET /api/academy/my/points — 我的积分与等级(总分/当前等级/距下一档/分项计数,唯一口径 lib/academy-points;未绑员工档案回零分 L1 空态;REQ-20261107-46 A 批预留、C 批页面消费)。权限:登录+组织归属

Certificates/api/academy/certificatesGET2 个接口

GET/api/academy/certificates

我的证书列表(默认当前登录用户的证书;可代查他人或查即将到期的证书)

GET/api/academy/certificates/{id}

证书详情(证书打印页数据源:证书 + 课程 + 员工全字段)

Admin75 个接口

Service Quotes/api/admin/service-quotesGETPOSTPATCH27 个接口

GET/api/admin/service-quotes/catalog

服务目录列表(ops;D138 批一/REQ-20261108-14):登录态+平台员工(platform_staff active,与 is_platform_staff() RLS 同源;细粒度矩阵归批三)。`?active=1` 只看启用。表未应用(migration 930 只写未应用)时诚实 500

POST/api/admin/service-quotes/catalog

新建服务目录项(ops;批一):body `{code*, name_i18n*, description_i18n?, sow_template?, pricing_model?, unit_price_cents?, tax_hint?, sort?}`;code 唯一(409 CATALOG_CODE_EXISTS),目录是数据、新增服务不发版

PATCH/api/admin/service-quotes/catalog/{id}

改目录项(ops;批一):改价只影响新 quote 带出,已发版本快照不受影响

POST/api/admin/service-quotes/quotes

建报价草稿(ops;批一):body `{organization_id*, draft*}`,取 QUOTE- 号、状态 draft(客户不可见)

GET/api/admin/service-quotes/quotes

报价列表(ops;批一):`?organization_id=&status=&limit=&offset=` 分页(limit 封顶 100)

GET/api/admin/service-quotes/quotes/{id}

报价详情(ops;批一):头+当前版本+对客留言+内部备注(ops 全量视图;内部备注仅出现在 ops 面端点,客户侧 DTO/端点永不引用该表)

PATCH/api/admin/service-quotes/quotes/{id}

改草稿(ops;批一):body `{draft*}`;draft/open 可改,终态 400 QUOTE_NOT_EDITABLE

POST/api/admin/service-quotes/quotes/{id}/send

发送报价(ops;批一):冻结生成新版本快照(全文 JSONB+canon-v1 SHA-256+行级差异摘要),头转 open;响应带 `discount_hint`(P-6 折让 15% 仅提示不拦截,拦截归批三);快照超 64KB 400 SNAPSHOT_TOO_LARGE

GET/api/admin/service-quotes/quotes/{id}/versions

版本列表只读回溯(ops;批一):每版全文快照+哈希+差异摘要;版本只追加不可变、无写方法

GET/api/admin/service-quotes/quotes/{id}/messages

议价留言列表(客户可见,ops;批一)

POST/api/admin/service-quotes/quotes/{id}/messages

ops 回复留言(批一):body `{body*, version_id?}`;author_side 服务端强制落 ops、客户端传值忽略

GET/api/admin/service-quotes/quotes/{id}/internal-notes

内部备注列表(**仅平台员工**,批一):内部备注在 API 面的唯一出口组;Portal 与 agent 工具查询面均不登记本表(D138 §7/§20)

POST/api/admin/service-quotes/quotes/{id}/internal-notes

新增内部备注(仅平台员工,批一):body `{body*}

GET/api/admin/service-quotes/orders

服务订单列表(ops;批一):`?organization_id=&status=&limit=&offset=` 分页

GET/api/admin/service-quotes/orders/{id}

服务订单详情(ops;批一):里程碑全表(付款维/交付维)+预生成 Invoice 草稿清单(草稿 invoice_no 为 null=未取 PINV- 号)

POST/api/admin/service-quotes/invoices/{id}/offline-payments

线下收款登记(ops 收款台;D138 批二):登录态+平台员工。body `{amount_cents*, provider*(manual_wire/manual_card_terminal/manual_check), method_details?, evidence?{file_ref*, file_name?}}`;登记≠到账——落 payments processing 行+证据行、不产生分配;发票非 service 源 400 INVOICE_NOT_SERVICE

POST/api/admin/service-quotes/invoices/{id}/offline-payments/{paymentId}/confirm

线下收款确认销账(ops 收款台;批二):确认人须≠登记人(400 OFFLINE_CONFIRM_MUST_DIFFER_FROM_RECORDER);确认后 payment→succeeded+落分配+按净 Σ 推进发票 paid/partially_paid 与里程碑付款维;超额 400 ALLOCATION_EXCEEDS_BALANCE;重复确认回放

POST/api/admin/service-quotes/invoices/{id}/recover-charge

dunning 恢复扣款(ops;批二):按当前余额重算 off-session 扣款(幂等:在途回放、余额 0 不扣),成功经分配销账自动解 blocked_hold;响应带 dunning 分区状态(source 分区+阶梯位)

POST/api/admin/service-quotes/invoices/{id}/writeoff

服务发票核销(ops;批二,D79 配套④):body `{reason*, approved_by*}`,批准人须≠申请人;adjustments writeoff 留痕→发票 uncollectible、里程碑关停;仅 service 源

POST/api/admin/service-quotes/billing/run-due

里程碑到期扫描(ops/调度;批二):billing-payment-retry 任务族转正式子任务的 core 执行入口——扫 on_date 到期且付款维 pending 的里程碑逐个转正式(取 PINV- 号)+按余额扣款,单条失败不阻塞全批、全程幂等

POST/api/admin/service-quotes/milestones/{id}/deliver

ops 标记里程碑交付(D138 批三):登录态+平台员工;body `{note*}`;落交付留痕 delivered_at/by/note、交付维 delivered,起点为验收 7 天窗(auto 提醒 T+3/+6、T+7 自动确认由扫描入口判定,定时驱动归 D79 任务族线、本入口不冒称自动运行);blocked_hold 期次 400 MILESTONE_BLOCKED_HOLD

POST/api/admin/service-quotes/billing/run-acceptance

验收超时扫描(ops/调度;批三,与 run-due 同范式):扫已过 7 天未确认的待验收期次逐个自动落痕验收并触发 on_acceptance 扣款;通道未配置时仍落痕、结果带 provider_ready=false;扫描入口即定时驱动契约,cron 注册归任务族线(见 D138 §24)

GET/api/admin/service-quotes/orders/{id}/amendments

变更单列表(ops;批三):四态(draft/sent/confirmed/rejected)全量

POST/api/admin/service-quotes/orders/{id}/amendments

新建变更单(ops;批三):body `{plan*}` 全计划快照;总额须与订单总额一致(400 AMENDMENT_TOTAL_MISMATCH)、已转正式/已扣期次金额与触发不可动(400 AMENDMENT_TOUCHES_SETTLED_MILESTONE);快照定稿即算 canon-v1 哈希

POST/api/admin/service-quotes/orders/{id}/amendments/{aid}/send

发送变更单(ops;批三):draft→sent,要求订单计划完整性复核通过;重入回放

POST/api/admin/service-quotes/invoices/{id}/refunds

服务发票退款执行(ops;批三,§11.2 单轨):body `{payment_id*, amount_cents*, reason*, requested_by*}`,执行人=会话员工且必须≠requested_by(双人分离硬校验);卡扣原路退款(幂等键 service-refund:<id>)、线下登记两路;allocations 落 refund_reversal 镜像+adjustments type='credit' 冲减分录;paid 发票不回落、partially_paid 按净 Σ 重算;超额 400 REFUND_EXCEEDS_ALLOCATED;同三元(payment+金额+理由)未失败退款重入回放不双退

GET/api/admin/service-quotes/pdf

服务单据 PDF(ops;批三):`?kind=quote&quote_id=&version_id=`(缺 version_id 取当前版)或 `?kind=invoice&invoice_id=`;内容以版本快照/发票落库事实为准、金额单号逐字一致,发票 PDF 含明细行(服务行 qty/unit/amount+税行);响应头 `X-Pdf-Document-Id`(内容哈希派生);quote 任意版本可下、ops 可下载草稿发票 PDF(渲染 draft 标记,Portal 侧草稿 404)

Roles/api/admin/rolesGETPOSTPATCHDELETE6 个接口

GET/api/admin/roles

本组织角色列表(仅 Owner/Admin),非模板,含每个角色的权限条数和成员数

POST/api/admin/roles

从角色模板新建角色(仅 Owner/Admin),复制模板的 role 行和权限到本组织

DELETE/api/admin/roles/{id}

删除角色(仅 Owner/Admin),仅限非 system 角色且无成员挂载

GET/api/admin/roles/{id}

角色详情(仅 Owner/Admin),含按 app_key 分组的权限矩阵

PATCH/api/admin/roles/{id}

更新角色(仅 Owner/Admin),可改名,permissions 数组以 (role_id, app_key, module) 为键全量替换

GET/api/admin/roles/templates

可用的角色模板列表(is_template=true),仅 Owner/Admin

计费/api/admin/billingGETPOST5 个接口

GET/api/admin/billing

租户账单(仅 Owner/Admin),返回当前订阅 + 发票列表(只读)

GET/api/admin/billing/payment-method

平台账单在档付款方式摘要(仅 Owner/Admin;R-1/REQ-20261108-14,D79 §3.3/§10.2)。数据:platform_billing_profiles(migration 929,只写未应用;未应用时诚实 500)

POST/api/admin/billing/payment-method

存卡第二步(仅 Owner/Admin;R-1):以 SetupIntent 得到的通道付款方式 id 落档——摘要只从 Stripe 回读组装,不采信客户端传来的 brand/last4

POST/api/admin/billing/payment-method/setup-intent

存卡第一步(仅 Owner/Admin;R-1):建/复用组织 Stripe 客户(id 落 profiles.stripe_customer_id)并创建 SetupIntent(usage=off_session,为商户发起扣款取同意),返回 client_secret 供前端 Stripe.js 收集卡片;卡数据只经 Stripe

POST/api/admin/billing/invoices/{id}/charge

对平台发票发起 off-session 整额扣款(仅 Owner/Admin 且发票须属当前组织;R-1 只做整额,分期/部分金额归 D138 批二)。幂等:已有 succeeded/processing/requires_action 尝试直接回放(charged=false)不重复扣;全部 failed 才以 attempt_no+1 新尝试

Export/api/admin/exportGETPOSTDELETE5 个接口

POST/api/admin/export

创建全量数据导出任务(仅 Owner),需 confirm 确认,每租户每天最多 3 次

GET/api/admin/export/jobs

导出任务列表(仅 Owner/Admin),按创建时间倒序,含进度百分比

DELETE/api/admin/export/jobs/{id}

取消进行中的导出任务(仅 Owner),任务变 cancelled、未做的表变 skipped

GET/api/admin/export/jobs/{id}

导出任务详情(仅 Owner/Admin),含任务整体进度和每张表的进度

GET/api/admin/export/jobs/{id}/download

下载导出 ZIP(仅 Owner/Admin),302 跳转到 7 天有效的 R2 预签名 URL,记录下载审计

Package Tiers/api/admin/package-tiersGETPOSTPATCHDELETE4 个接口

GET/api/admin/package-tiers

列出平台套餐档位(含停用),按 product 和 sort_order 排序;平台员工鉴权(billing.view 权限)。

POST/api/admin/package-tiers

新建平台套餐档位(产品类型限 sms/storage/ai_token);平台员工鉴权(billing.view 权限)。

DELETE/api/admin/package-tiers/{id}

硬删除单个套餐档位(前端二次确认);平台员工鉴权(billing.view 权限)。

PATCH/api/admin/package-tiers/{id}

编辑单个套餐档位(名称/数量/价格/排序/启停,按需传字段);平台员工鉴权(billing.view 权限)。

Sms/api/admin/smsGETPOSTPATCH4 个接口

GET/api/admin/sms

租户短信流量包信息(仅 Owner/Admin),含余额/开关/模式和在售套餐

PATCH/api/admin/sms

更新租户短信开关(仅 Owner/Admin),可开关短信功能和切换模式

POST/api/admin/sms/buy

租户购买短信流量包(仅 Owner/Admin),首版付款 stub:直接加余额并写购买记录

GET/api/admin/sms/logs

租户短信发送记录(仅 Owner/Admin),支持状态/通道/时间筛选与分页

Account/api/admin/accountPOST3 个接口

POST/api/admin/account/close

发起关闭账号(仅 Owner),需输入租户名确认,组织进入 closing 并冻结非 Owner 成员登录,90 天保留期后可恢复

POST/api/admin/account/close-check

关闭账号前检查(仅 Owner),返回未完成导出、未结账单、是否为唯一 Owner 及能否关闭

POST/api/admin/account/restore

保留期内恢复账号(仅 Owner),account_status 从 closing 回到 active 并恢复成员登录

Staff/api/admin/staffGETPOSTPATCH3 个接口

GET/api/admin/staff

员工列表(仅 Owner/Admin),含用户邮箱/显示名/状态/角色和封禁标记

POST/api/admin/staff

新建员工(仅 Owner/Admin):建 Auth 用户 → 加组织成员 → 分配角色,任一步失败自动回滚

PATCH/api/admin/staff/{id}

员工管理操作(仅 Owner/Admin):停用/启用/重置密码/换角色,组织至少保留一个 active owner

Email Intake/api/admin/email-intakeGETPOST3 个接口

GET/api/admin/email-intake/settings

AI Assistant 设置读取(REQ-20261030-02 设计稿 D69 §6/§8;配置面 2026-10-30 迁 Admin,REQ-20261030-14):本租户收信地址 + 历史别名清单 aliases(旧名+启用/停用时间,REQ-20261030-16 接线)+ 改名下次可改时间 rename_next_available_at(冷却中给 ISO、可改给 null)+ 发件人白名单 + 能力矩阵(代码注册表 × 租户档位合成)+ 货主列表。Admin 鉴权(Owner/Admin),组织隔离。原 `/api/oms/email-intake/settings` 已下线。**REQ-20261031-74 加法扩**:brand(组织品牌 platform_organizations.brand)+ brand_policies(品牌能力档位策略行)+ visible_capability_codes(该品牌可见能力码,orderball 只四件)+ brand_intake_domain + address_local_part_strategy(orderball=random 随机串、docklify=name);能力行加 brand_default_tier/brand_max_tier,租户未设档时品牌默认顶上 capabilities.tier。

POST/api/admin/email-intake/settings

AI Assistant 设置写动作(action 分发:ensure_address 开通地址 / toggle_address 停启用 / add_sender 加白名单(邮箱条目即发确认信,token 只存 sha256;域名条目置 pending_platform_review;**域名命中公共邮箱域清单(含子域)硬拒绝 PUBLIC_DOMAIN_BLOCKED**,REQ-20261030-14)/ update_sender / delete_sender / set_capability 设能力档(服务端按注册表风险上限硬校验;D75 一期起支持 channel 参数〔email/rollie〕,按 ASSISTANT_CAPABILITIES 双渠道夹取,未实现格恒 off)/ set_switch 租户渠道总开关(D75 §4.2;邮件渠道手动开启须先配齐地址+已验真发件人,未配齐回 EMAIL_NOT_READY 大白话)/ set_platform_switch 平台总闸(仅 platform_staff active 可操作,必填 reason,按目标组织落 scope='platform' 行〔P2-1 定版,与租户行分开、恢复各自打开〕,强审计 assistant.switch_changed+只通知目标租户管理员,动作单点 lib/assistant-platform-switch;ops 入口经 /api/ai/internal/assistant-switch 同口径)/ save_reply_settings 回复设置与签名与 Rollie 呈现(语言三模式/签名/附链接/附货物摘要/追问上限/Rollie 显示名·欢迎语·默认档,落 email_intake_settings+assistant.* 审计)/ rename_address 改收信地址名(REQ-20261030-16 接线:状态判定与写入全在 lib 单事务 RPC rename_email_intake_address——双池占用、30 天冷却〔首次免费〕、改回自家旧名;失败 400+错误码 NAME_TAKEN / NAME_RESERVED / NAME_INVALID〔detail.issue 细分 empty/too_short/too_long/bad_chars/edge_hyphen〕 / NAME_UNCHANGED / COOLDOWN〔detail.next_available_at〕 / ADDRESS_NOT_FOUND / RENAME_FAILED;成功落审计 email_intake.address_renamed〔from→to〕+通知管理员 reason=address_renamed)/ check_address_name 改名实时可用性预查(不落库,回 { available, code, issue?, next_available_at? };预查仅提示,并发最终判定以 RPC+名字注册表唯一约束为准))。全部动作落 wms_audit_log(真实用户)+变更通知租户管理员。**REQ-20261031-74 新增 reset_address**(重置专属地址:安全动作不走 30 天改名冷却——独立 RPC reset_email_intake_address,与改名同套占用/注册表语义;旧址按品牌宽限处理,orderball 宽限 7 天只收不办+提醒、绝不回告新址;审计 email_intake.address_reset)/ensure_address 对 random 本地名品牌单次生成直插/set_capability 对 email 渠道追加品牌上限夹取(assistant_brand_policies.max_tier)/rename_address 与 check_address_name 的域名按品牌解析。**REQ-20261103-21 加法**:orderball 品牌收信域改 ai.orderball.com(intakeDomainForBrand 单点,ensure/rename/reset/check 同动;存量旧域地址经别名全址匹配继续可达);save_reply_settings 的 signature 扩结构化键(enabled/assistant_name/title/company/phone/website/address/extra_lines/support_email)并服务端归一(键白名单/长度上限/控制字符清洗/website 须 http(s):// 开头、support_email 须含 @ 才保留,其余键不变,lib normalizeSignatureForSave 单点);助理出信经 OMS runtime sendReply 单点按组装函数 assembleAssistantSignature(存储 jsonb+组织名+brand_logo_url+回信语言,含 signature_by_lang 覆盖与品牌感知默认名)附 text/html 双形态签名(D75 D-MS7 接线补完),组装异常降级为无签名照常发信。

GET/api/admin/email-intake/settings`(D75 一期扩展)

GET 响应加法扩:switches(双渠道双层有效值:租户行/平台总闸行/合成 enabled)、assistant_capabilities(双渠道能力矩阵)、reply_settings、usage(本月受理/成单/转人工,服务端聚合)、pending_verification_count、activity(assistant.+email_intake. 前缀近期审计)、email_enable_ready。

Ai App Settings/api/admin/ai-app-settingsGETPUT2 个接口

GET/api/admin/ai-app-settings

读取租户各 APP 的 AI 功能开关,缺行默认开启

PUT/api/admin/ai-app-settings

批量更新租户各 APP 的 AI 功能开关(仅 Owner/Admin)

App Settings/api/admin/app-settingsGETPUT2 个接口

GET/api/admin/app-settings

读取租户各 APP 的启用开关,缺行默认开启(admin 应用永远开启且锁定不可关)

PUT/api/admin/app-settings

批量更新租户各 APP 的启用开关(仅 Owner/Admin,锁定应用不能关)

Organization/api/admin/organizationGETPATCH2 个接口

GET/api/admin/organization

读取当前组织的设置(id/名称/时区/语言/币种/国家/公司类型+市场档案:日期格式/单位制/税号+品牌 logo brand_logo_url,D68/migration 714)

PATCH/api/admin/organization

更新组织设置(仅 Owner/Admin),只接受白名单字段(名称/时区/默认语言/币种/国家/日期格式/单位制/税号/品牌 logo)

Permissions/api/admin/permissionsGETPATCH2 个接口

GET/api/admin/permissions

全局权限矩阵(仅 Owner/Admin),返回角色列表、全部模块去重列表和按角色的权限矩阵

PATCH/api/admin/permissions

一次提交全量权限矩阵(仅 Owner/Admin),每个角色以 (role_id, app_key, module) 为键全量替换

仓库/api/admin/warehousesGETPOST2 个接口

GET/api/admin/warehouses

仓库列表(仅 Owner/Admin,管理用),全部仓库含停用的,支持编码/名称搜索和启用状态筛选

POST/api/admin/warehouses

新建仓库(仅 Owner/Admin),code 在同组织内唯一

Ai Usage/api/admin/ai-usageGET1 个接口

GET/api/admin/ai-usage

租户 AI token 用量(仅 Owner/Admin),加油包模式:汇总/按 APP/按用户/30 天趋势

Audit/api/admin/auditGET1 个接口

GET/api/admin/audit

租户审计日志(仅 Owner/Admin),支持时间范围/操作人/动作筛选与分页,另附本租户出现过的动作类型下拉

Context/api/admin/contextGET1 个接口

GET/api/admin/context

当前用户的 Admin 上下文(是否管理员/组织信息/启用的 APP),供 Waffle 菜单过滤和页面级鉴权

Dashboard/api/admin/dashboardGET1 个接口

GET/api/admin/dashboard/summary

租户 Admin Dashboard 聚合数据(仅 Owner/Admin),一次返回 KPI/订阅/短信-存储-AI 资源卡/告警

Subscription/api/admin/subscriptionGET1 个接口

GET/api/admin/subscription

订阅计划(仅 Owner/Admin),返回当前订阅 + 可选计划列表(首版为展示预览,升级走联系销售)

Agent4 个接口

V1/api/agent/v1GETPOST4 个接口

POST/api/agent/v1/pair

配对交换(无 Bearer,配对码即凭据):{code, employee_no} → agt_ 正式凭证(90 天),agent 进待确认态;失败只回通用 PAIRING_FAILED、细分码仅给持码方;错码归因锁定 5 次(归因边界见 D30 修订注记);端点带 IP 维失败粗限速。

GET/api/agent/v1/me

agent 自检:身份(名字+员工号)/店铺/岗位工具清单与生效三档(含 V1 写封顶标记)/巡访规则/凭证到期;待确认态唯一可用端点。鉴权:agt_ Bearer。

POST/api/agent/v1/heartbeat

pull 巡访心跳(限 12/h/凭证):回执带配置版本(变更时回生效档全量配置)+近 24h 已决提议+待提计数+凭证剩余天数。鉴权:agt_ Bearer(须已确认)。

POST/api/agent/v1/tools/{tool}

工具调用(读限 300/h、写与提议限 60/h/凭证):三档在工具层逐调用强制(岗位∩店主配置∩平台封顶∩单 org),写必带 Idempotency-Key;平台五件(退款/删商品/改连接与设置/凭证值/买家联系方式)永不可达;V1 写全封顶提议档。鉴权:agt_ Bearer(须已确认)。

Agent Actions1 个接口

Agent Actions/api/agent-actionsGET1 个接口

GET/api/agent-actions

查平台 Action 注册表(只读),列出 Agent 可编排的全部动作定义(含参数 schema)。

Agent Calendar4 个接口

Agent Calendar/api/agent-calendarGETPOSTPATCH4 个接口

GET/api/agent-calendar

查 Agent 统一日历事件;agent_id 不传=查全部 agent(全局日历),from/to 为 ISO 时间范围,status 支持多值逗号分隔。

POST/api/agent-calendar

在 Agent 统一日历建日程;同一 agent 时间重叠返回 409(error=time_conflict 并带 conflicts 列表)。

GET/api/agent-calendar/{id}

查 Agent 统一日历里的单个事件

PATCH/api/agent-calendar/{id}

更新日历事件(改时间会自动做冲突检查,冲突返回 409)

Agent Roles4 个接口

Agent Roles/api/agent-rolesGETPOSTPATCH4 个接口

GET/api/agent-roles

查平台 Agent Role 列表(只返回 scope=platform 的),每行附带关联的 Topic 数量。

POST/api/agent-roles

新建平台 Agent Role;name 重名返回 409(error=name_exists)。

GET/api/agent-roles/{id}

查一个 Agent Role 的详情(含关联的 Topics)

PATCH/api/agent-roles/{id}

更新一个 Agent Role(含其关联的 Topic 列表)

Agent Topics4 个接口

Agent Topics/api/agent-topicsGETPOSTPATCH4 个接口

GET/api/agent-topics

查平台 Agent Topic 列表(scope=platform/shared),每行附带关联的 Action 数和 Role 数。

POST/api/agent-topics

新建平台 Agent Topic(含 SOP 和有序的 Action 步骤);name 重名返回 409(error=name_exists)。

GET/api/agent-topics/{id}

查一个 Agent Topic 的详情(含关联的 Actions 列表)

PATCH/api/agent-topics/{id}

更新一个 Agent Topic(含其 Action 步骤清单)

Agent Wakeup1 个接口

Agent Wakeup/api/agent-wakeupPOST1 个接口

POST/api/agent-wakeup

内部调度器叫醒租户 Agent:验 x-internal-secret 头,确认 agent 是 scope=tenant 且 active 后写一条 ai_agent_actions 审计记录。

Agent Wakeups1 个接口

Agent Wakeups/api/agent-wakeupsGET1 个接口

GET/api/agent-wakeups

查某个 Agent 的待处理叫醒任务(agent_wakeups 中 status=pending 的),按 wake_at 排序。

Agents2 个接口

Actions/api/agents/actionsPOST2 个接口

POST/api/agents/actions/{id}/approve

批准一个 proposed 状态的 Agent 动作并立即执行(proposed → approved 记审计 → 执行);平台员工鉴权。

POST/api/agents/actions/{id}/reject

拒绝一个 proposed 状态的 Agent 动作(记审计,不再执行);平台员工鉴权。

Ai13 个接口

Scene Images/api/ai/scene-imagesGETPOST6 个接口

POST/api/ai/scene-images/jobs

给产品图生成 AI 场景图,提交异步任务(Token 预授权),成功返回 202

GET/api/ai/scene-images/jobs/{id}

轮询 AI 场景图任务状态,前端约 30–60 秒查一次

GET/api/ai/scene-images/remove-bg

轮询去背景任务状态(fal.ai BiRefNet)

POST/api/ai/scene-images/remove-bg

给产品图去背景,同步返回结果(约 $0.01/次)

POST/api/ai/scene-images/save

用户从候选图里选中 1 张,存入产品图片库

GET/api/ai/scene-images/templates

AI 场景图的 Prompt 模板列表

Teaching/api/ai/teachingGETPOST2 个接口

GET/api/ai/teaching

Docklify AI 教学提交列表(REQ-20261106-43 W4 / D107 §32.2):本 org 教学提交(migration 912 ai_teaching_submissions),query `status?(submitted/reviewed/used)/limit?/offset?`,created_at 倒序、`.range()` 有界分页。响应 `{submissions}`。逻辑单点 `@docklify/lib/ai-requests`。912 未应用时统一回 503 `AI_SETUP_PENDING` 人话。鉴权 resolveAdminContext+requireAdmin+organization_id 隔离

POST/api/ai/teaching

Docklify AI 提交教学:body `{title*, scenario_description*, positive_example*, negative_example?, warehouse_id?}`。v1 只收文字说明、不收文件(示例媒体上传后置);落库恒 `submitted`,状态推进在平台侧。错误:400 `AI_VALID_001`(必填缺失/仓库 id 形态不对/所选仓库不属本组织;信封 detail 带人话,教学页按码映射六语人话呈现,不直显裸码)/ 503 `AI_SETUP_PENDING` / 500 `AI_SERVER_001`。响应 `{submission}

Requests/api/ai/requestsGETPOST2 个接口

GET/api/ai/requests

Docklify AI 特殊需求提单列表(REQ-20261106-43 W4 / D107 §30.10·§32.2):本 org 提单(migration 912 ai_custom_requests),query `status?(submitted/triaging/scheduled/in_production/delivered/closed)/limit?/offset?`。响应 `{requests}`,含平台侧回写的判层结论 `ladder_verdict`(未判层为 null)。**提单状态流即训练进度页的唯一数据源**,不另建进度存储。逻辑单点 `@docklify/lib/ai-requests`。鉴权同上

POST/api/ai/requests

Docklify AI 提特殊需求:body `{title*, scene_type*, description*, expected_outcome?}`,落库恒 `submitted`、`ladder_verdict` 恒空(判层在平台侧回写、租户不许自填)。错误:400 `AI_VALID_001` / 503 `AI_SETUP_PENDING` / 500 `AI_SERVER_001`。响应 `{request}`。本组端点不新增 AI/agent 工具登记(租户写操作面,承 §31.7 控制类不经 agent 口径)

Chat/api/ai/chatPOST1 个接口

POST/api/ai/chat

AI 助手网关(SSE 流式):用户发消息,网关走 AI Router 调模型做问答/工具查询,写操作只返确认卡片不执行;超限直接返回 quota_exceeded;租户用户只能用自己组织的配额。

Token Balance/api/ai/token-balanceGET1 个接口

GET/api/ai/token-balance

当前组织 AI Token 可用余额(真实接口)

Usage/api/ai/usageGET1 个接口

GET/api/ai/usage

AI 用量查询:某组织的本月配额(套餐名/月额度/已用/占比)+ 个人本月用量明细。

Ai Agents5 个接口

Ai Agents/api/ai-agentsGETPOST3 个接口

GET/api/ai-agents/{id}/ontology

查某个 AI agent 的 Role 和关联的 Topics

POST/api/ai-agents/{id}/ontology

给 AI agent 分配角色和话题

GET/api/ai-agents/{id}/tasks

查某个 AI agent 拥有的任务列表

Roles/api/ai-agents/rolesGET1 个接口

GET/api/ai-agents/roles

当前租户可用的 AI agent 角色列表(scope=tenant)

Topics/api/ai-agents/topicsGET1 个接口

GET/api/ai-agents/topics

当前租户可见的 AI agent 话题列表(scope=tenant/shared)

Ai Providers3 个接口

Ai Providers/api/ai-providersGETPATCH2 个接口

GET/api/ai-providers

列出 AI 路由三个 provider 的配置(litellm/openrouter/openai):是否启用、优先级、默认模型、key 是否已配(只给布尔值,绝不返回 key 明文);平台员工鉴权。

PATCH/api/ai-providers

更新 AI provider 配置(启停/优先级/默认模型),或设置某个场景的默认模型;平台员工鉴权。

Health/api/ai-providers/healthPOST1 个接口

POST/api/ai-providers/health

测试指定 AI provider 的连通性(绕开 failover 链,直发最小 chat 请求);平台员工鉴权。

Ai Usage4 个接口

Config/api/ai-usage/configGETPUT2 个接口

GET/api/ai-usage/config

AI 免费额度+硬停开关配置(只读,平台员工会话鉴权):返回全局默认行+全部档位覆盖行;配置表未应用时回落默认(免费 0、硬停关)并标 config_available=false。

PUT/api/ai-usage/config

AI 免费额度+硬停开关配置写(平台员工会话鉴权;body {scope: global

Ai Usage/api/ai-usageGET1 个接口

GET/api/ai-usage

ops「AI 用量」总览(REQ-20261026-11,平台员工会话鉴权)。参数 from/to(UTC 日,缺省近 30 天)+org_id 下钻;历史日读按天 rollup+今日读 logs 实时聚合,返回总量/日趋势/按租户/按产品/按 app/按模型/按层级+本月配额占用(已用 vs 免费额度配置+加油包)+桥 token 并列卡(自报口径、不混算)。

Rollup/api/ai-usage/rollupPOST1 个接口

POST/api/ai-usage/rollup

手动刷新 AI 用量按天 rollup(平台员工会话鉴权;body {from,to},区间上限 92 天;调 refresh_ai_usage_rollup 幂等重灌,返回写入行数)。

Analytics30 个接口

Subscriptions/api/analytics/subscriptionsGETPOSTPUTDELETE7 个接口

GET/api/analytics/subscriptions

本组织订阅列表

POST/api/analytics/subscriptions

新建订阅(定时把报表/仪表盘发到收件人邮箱)

DELETE/api/analytics/subscriptions/{id}

删除订阅(本组织,投递日志级联删除)

GET/api/analytics/subscriptions/{id}

订阅详情(本组织)

PUT/api/analytics/subscriptions/{id}

更新订阅;status 走状态机校验(active→paused/cancelled,paused→active/cancelled,failed→active)

GET/api/analytics/subscriptions/{id}/deliveries

订阅投递记录

GET/api/analytics/subscriptions/email-status

邮件服务是否已配置(只返回布尔值,不泄露 key;UI 未配置时顶部诚实提示)

Dashboards/api/analytics/dashboardsGETPOSTPUTDELETE6 个接口

GET/api/analytics/dashboards

仪表盘列表:本组织自建 + 全局预置(预置跨组织只读)

POST/api/analytics/dashboards

新建仪表盘(is_preset 强行锁定为 false)

DELETE/api/analytics/dashboards/{id}

删除仪表盘(仅本组织自建;删预置报 403)

GET/api/analytics/dashboards/{id}

仪表盘详情(预置跨组织只读)

PUT/api/analytics/dashboards/{id}

更新仪表盘(仅本组织自建;改预置报 403)

POST/api/analytics/dashboards/{id}/copy

复制仪表盘,为本组织新建一份

Reports/api/analytics/reportsGETPOSTPATCHDELETE6 个接口

GET/api/analytics/reports

报表定义列表(附数据源白名单 sources)

POST/api/analytics/reports

新建报表定义(config 走白名单校验)

DELETE/api/analytics/reports/{id}

删除报表定义(本组织)

GET/api/analytics/reports/{id}

报表定义详情(本组织)

PATCH/api/analytics/reports/{id}

更新报表定义(config 重新走白名单校验)

POST/api/analytics/reports/{id}/run

按报表 config 执行聚合返回结果;id=preview 时用 body.config 临时运行(不入库);body.config 可合并覆盖 filters

Alerts/api/analytics/alertsGETPOSTPATCHDELETE4 个接口

GET/api/analytics/alerts

本组织告警规则列表

POST/api/analytics/alerts

新建告警规则(只建可计算的 KPI,否则规则永远不会触发)

DELETE/api/analytics/alerts/{id}

删除告警规则(本组织,触发记录级联删除)

PATCH/api/analytics/alerts/{id}

更新告警规则(本组织)

Insights/api/analytics/insightsGETPOST3 个接口

POST/api/analytics/insights/ask

自然语言问数:AI 从问题里解析意图(KPI 代码+时间范围,只能选 KPI 目录内的),答不上来会澄清

GET/api/analytics/insights/events

AI 洞察异常事件流:KPI 实时值 vs 行业 benchmark + 告警规则触发历史

GET/api/analytics/insights/queries

自然语言问数的问答历史(本组织,created_at 倒序)

Kpis/api/analytics/kpisGET2 个接口

GET/api/analytics/kpis

KPI 定义库(按模块筛选,name/definition 可多语言)

GET/api/analytics/kpis/{code}/value

KPI 实时值(实时值计算引擎,50 个 KPI 中 25 个真实计算,暂算不出的 value 为 null;按租户缓存 15 分钟)

Query/api/analytics/queryPOST1 个接口

POST/api/analytics/query/run

统一查询引擎:语义字段(须在语义注册表登记)→ 复用报表聚合引擎执行,每次执行写审计日志

Snapshots/api/analytics/snapshotsGET1 个接口

GET/api/analytics/snapshots

KPI 历史快照趋势(供趋势图用)

Assets46 个接口

Assets/api/assets/assetsGETPOSTPATCHDELETE13 个接口

GET/api/assets/assets

设备台账 → 设备列表(Assets App 模块 1)。筛选 status(in_use/under_repair/idle/scrapped) / asset_type(forklift/pallet_jack/scanner/label_printer/dock_door/dock_leveler/other) / warehouse_id / q(asset_no/model/notes 模糊)。

POST/api/assets/assets

新建设备。asset_no 为空自动取号 AST-000001(shared_doc_sequences.ast_asset 原子取号);手工编号做租户内唯一性校验(409);qr_code 自动生成详情页 URL 回写;初始状态只允许 in_use / idle。

DELETE/api/assets/assets/{id}

删除设备(租户内)。TODO(模块2/3/4):点检/维修/借用产生关联记录后改为软拦。

GET/api/assets/assets/{id}

设备详情(含 warehouse: {id, code, name} 展开)。扫码落地页 /assets/[id] 调本接口。

PATCH/api/assets/assets/{id}

编辑设备。白名单字段:model / purchase_date / warehouse_id / location_text / notes;asset_no 允许改号(租户内唯一性校验,409);已报废(scrapped)设备锁定,返回 400。

GET/api/assets/assets/{id}/inspections

某设备的点检历史:倒序分页,每单含检查项明细和是否报修

POST/api/assets/assets/{id}/inspections

提交一次设备点检:任一不合格整单不合格,关键项不合格自动把设备置为维修中(同天重复提交 409,可带 force 覆盖)

GET/api/assets/assets/{id}/maintenance

某设备的维修/保养记录列表:倒序分页,可按类型过滤

POST/api/assets/assets/{id}/maintenance

新增一条设备维修/保养记录:做保养可回写排程并推算下次到期,维修可关联工单

DELETE/api/assets/assets/{id}/photos

删除某设备的一张照片(含 Storage 里的文件)

GET/api/assets/assets/{id}/photos

某设备的照片列表,每张带 1 小时有效的签名下载 URL

POST/api/assets/assets/{id}/photos

上传设备照片:每台最多 5 张,只收 JPG/PNG/WebP/HEIC 且单张 ≤10MB

POST/api/assets/assets/{id}/status

设备状态变更,走状态机校验:in_use ⇄ idle → under_repair → in_use/idle;任何状态 → scrapped(报废为终态,不可逆);非法流转 400。

Inspection Templates/api/assets/inspection-templatesGETPOSTPATCHDELETE9 个接口

GET/api/assets/inspection-templates

点检模板列表(含检查项):可按设备类型过滤,叉车首次使用会自动生成 OSHA 标准模板

POST/api/assets/inspection-templates

新建点检模板:只传 asset_type 取默认模板,不传 name 时自动生成/返回默认模板

DELETE/api/assets/inspection-templates/{id}

删除点检模板(检查项级联删除,历史点检记录不受影响)

GET/api/assets/inspection-templates/{id}

点检模板详情(含检查项,按序号排序)

PATCH/api/assets/inspection-templates/{id}

维护点检模板:重命名或设为默认(同设备类型内唯一默认)

PATCH/api/assets/inspection-templates/{id}/items

批量更新模板检查项(排序/文本/分类/关键项)

POST/api/assets/inspection-templates/{id}/items

给点检模板新增一个检查项(不传 seq 则追加到末尾)

DELETE/api/assets/inspection-templates/{id}/items/{itemId}

删除模板的一个检查项,剩下的序号自动重排为 1..n(历史点检记录不受影响)

PATCH/api/assets/inspection-templates/{id}/items/{itemId}

修改模板的一个检查项(文本/分类/关键项/序号),历史点检记录不受影响

Spare Parts/api/assets/spare-partsGETPOSTPATCHDELETE7 个接口

GET/api/assets/spare-parts

备件主数据列表:实时算每个备件的库存,库存 ≤ 补货点的打低库存预警标记

POST/api/assets/spare-parts

新建备件主数据:备件编号组织内不能重复

DELETE/api/assets/spare-parts/{id}

停用备件(软删:is_active 置 false)

GET/api/assets/spare-parts/{id}

备件详情:含实时库存和最近 20 条出入库流水

PATCH/api/assets/spare-parts/{id}

编辑备件主数据(库存不经这里改,只走出入库流水)

GET/api/assets/spare-parts/moves

备件库存流水列表:可按备件或类型过滤,每条含备件编号名称

POST/api/assets/spare-parts/moves

记一笔备件出入库流水:入库为正数、出库为负数、调整可正可负不能为 0

Maintenance Plans/api/assets/maintenance-plansGETPOSTPATCHDELETE5 个接口

GET/api/assets/maintenance-plans

保养计划列表(模板):可按设备类型过滤,叉车首次用时自动生成默认计划

POST/api/assets/maintenance-plans

新建保养计划:只传 asset_type 取默认计划,不传 name 时自动生成/返回默认计划

DELETE/api/assets/maintenance-plans/{id}

删除保养计划:已有设备挂着该计划时不可删

GET/api/assets/maintenance-plans/{id}

保养计划详情

PATCH/api/assets/maintenance-plans/{id}

更新保养计划:名称/周期/说明/启用状态,改名同类型内查重

Loans/api/assets/loansGETPOSTPATCH4 个接口

GET/api/assets/loans

设备借用单列表:按状态/逾期/设备/关键词过滤,超应还日未归还的标逾期

POST/api/assets/loans

新建设备借用申请:应还日不能早于借出日,设备已借出中会 409

GET/api/assets/loans/{id}

借用单详情(含设备快照和是否逾期)

PATCH/api/assets/loans/{id}

借用单状态流转:批准/拒绝(需原因)/借出/归还,借出前再验设备未被借出

Maintenance Schedules/api/assets/maintenance-schedulesGETPOST2 个接口

GET/api/assets/maintenance-schedules

保养排程列表:可按设备或状态过滤,每条含计划和设备展开信息

POST/api/assets/maintenance-schedules

给设备挂一个保养计划:计划只适用于同类型设备,同一计划挂两次会 409

Inspection Status/api/assets/inspection-statusGET1 个接口

GET/api/assets/inspection-status

批量查多台设备今日点检状态(设备列表页"今日点检"列一次查多台,避免 N+1)

Inspections/api/assets/inspectionsPOST1 个接口

POST/api/assets/inspections/{id}/repair-ticket

不合格点检一键报修:自动生成设备维修工单(关键项不合格优先级为 high),已建过直接返回现有工单

Maintenance Costs/api/assets/maintenance-costsGET1 个接口

GET/api/assets/maintenance-costs

维修/保养费用统计:看哪台设备最烧钱或某段时间花了多少,可按设备或按月汇总

Maintenance Due/api/assets/maintenance-dueGET1 个接口

GET/api/assets/maintenance-due

保养到期提醒:已过期和快到期的排程(快到期=7 天内或小时剩余不足 10%),每次按最新规则重算回写

Maintenance Records/api/assets/maintenance-recordsGET1 个接口

GET/api/assets/maintenance-records/{id}

维修/保养记录详情(含设备编号和关联工单号)

仓库/api/assets/warehousesGET1 个接口

GET/api/assets/warehouses

仓库下拉选项(新建向导用):本租户启用的仓库 id / code / name。

Auth7 个接口

Session Check/api/auth/session-checkPOST2 个接口

POST/api/auth/session-check

会话并发硬限制校验(登录成功后调用):上报当前设备信息,服务端按租户配额(默认每种设备类型 1 台,可超配)做去重/配额检查。未登录 401;超配额时返回已登记设备列表供前端提示踢设备。

POST/api/auth/session-check

会话并发硬限制校验(登录成功后调用):上报当前设备信息,服务端按租户配额(默认每种设备类型 1 台,可超配)做去重/配额检查。未登录 401;超配额时返回已登记设备列表供前端提示踢设备。

Session Heartbeat/api/auth/session-heartbeatPOST2 个接口

POST/api/auth/session-heartbeat

设备心跳,每 5 分钟上报一次更新活跃时间并检查设备是否被踢

POST/api/auth/session-heartbeat

设备心跳,每 5 分钟上报一次更新活跃时间并检查设备是否被踢

Sessions/api/auth/sessionsDELETE2 个接口

DELETE/api/auth/sessions/{device_id}

踢掉指定设备,只操作当前用户自己的设备(置 revoked=true 而非删行)

DELETE/api/auth/sessions/{device_id}

踢掉指定设备,只操作当前用户自己的设备(置 revoked=true 而非删行)

Signout/api/auth/signoutPOST1 个接口

POST/api/auth/signout

退出登录:清除 Supabase 会话后 302 跳转到对应语言的登录页。

Automation Switches2 个接口

Automation Switches/api/automation-switchesGETPOST2 个接口

GET/api/automation-switches

自动任务总开关列表(ops 平台端,REQ-20261024-28):返回全部 34 个开关 key 的目录信息与生效状态。平台员工鉴权(monitoring.view 权限)。

POST/api/automation-switches

设置自动任务开关(ops 平台端,REQ-20261024-28)。平台员工鉴权(monitoring.view)且 staff 角色须为 owner;task_key 必须在目录内,否则 400。upsert 开关行(updated_by=员工邮箱)并写 admin 审计 automation.switch_toggle。开关下一次触发即生效,无需发版。

Board`(Ops 页面,非 API)1 个接口

Board`(Ops 页面,非 API)/agents/board`(ops 页面,非 API)GET1 个接口

GETagents/board`(ops 页面,非 API)

GET agents/board — Agent 看板(REQ-20261025-12,套件设计 §9):ops 独立页(admin 部署,agents.view 权限),无新增 API 端点;数据经 admin 数据层共享统计函数 getBridgeStatsForAgent(与 -06 详情页统计条同源:归属 events.agent_id+空值行 handler 别名兼容;今日=America/Los_Angeles 自然日、近 30 天=滚动 30×24h)+值班段 agent_duty_sessions(包2 口径)服务端聚合;ai_agents 读走 service_role(员工 JWT 对该表无 RLS 读策略,照 platform-requests 先例);手动刷新+60 秒自动刷新;REQ-20261028-01 增补三项派生指标(套件设计 §9.6,口径函数 lib/db/board-metrics.ts):解决率(随窗)、积压预计清完(恒 d30 口径)、最久待处理年龄+超龄标红(pending 存量按 created_at 取最老一件,limit 1),零新端点、零迁移

Bridge4 个接口

Callback/api/bridge/callbackPOST1 个接口

POST/api/bridge/callback

POST /api/bridge/callback — Agent 回推入口(REQ-20261024-58,设计 §5.2):HMAC-SHA256 签名头 X-Bridge-Signature(t=<unix>,v1=<hex>,5 分钟窗),无登录会话。body { ticket_id(assist 会话 id), event_id?, type, agent_seq, agent_id?, bridge_status?, message?, evidence?, link_ticket_id?, handler?, token_used_delta? };type 按注册表分发 bridge.status/message/evidence/handoff/ticket_link;(ticket_id,type,agent_seq) 幂等不双写线程;状态只许前进;关单只认 evidence(connection.test_failed=retest_result,assist.escalated=user_confirmation/server_recheck 二选一);对客 message 过输出拦截;未配密钥 503 BRIDGE_NOT_CONFIGURED、555 未应用 503 BRIDGE_NOT_READY;作用域不分有无 event_id(无 event_id 以会话最新桥事件为锚,从未 emit 过的会话 403 CALLBACK_SCOPE_MISMATCH+审计,P2-1);验签失败 401 同时落审计(来源/时间/失败原因类别+载荷哈希,不落签名原文,P2-2);关单后迟到 failed 证据全量重开(桥状态/会话终态/事件 closed_at/互链缺陷单一致回待处理,P2-3);被守卫拦下的回推 token_used_delta 照实计量;REQ-20261025-06 起命中 Support 绑定(agent_id=Support 的 ai_agents.id,按名解析)的已应用回推另写穿一条 ops 工作日志(响应带 work_log: written/failed 计数,写失败不阻断回推);REQ-20261025-10 起同口收值班回推 duty.start/duty.end(agent 级、无 ticket_id,必填 agent_id+agent_seq,验签后先于 ticket_id 必填校验分流到 lib 注册表 DUTY_CALLBACK_HANDLERS;agent_id 必须命中服务端绑定解析,不命中 403 CALLBACK_SCOPE_MISMATCH+审计;幂等空间 (agent_id,type,agent_seq),审计行 callbacks.ticket_id 以 ai_agents.id 充锚;end_reason 只采信 idle_timeout/error、余归 manual,paused 只许平台关段写;已应用 duty 回推同样写穿工作日志);REQ-20261025-11 子集 B 起双验并行:Authorization: Bearer agt_… 令牌(按 agent 签发、只存 SHA-256 哈希、默认 90 天有效,ops Agents 详情页「桥凭证」区签发/轮换/吊销、全程审计)与 HMAC 任一通过即可,令牌路身份以令牌为准——自报 agent_id 为 UUID 形态且与令牌身份不符 403 CALLBACK_SCOPE_MISMATCH+审计,duty 回推按令牌绑定校验归属;无令牌且未配 HMAC 密钥维持 503;REQ-20261025-36 起作用域补工单锚:带 event_id 时事件锚=本会话互链工单(session.ticket_id)亦放行,不带 event_id 时先按会话查、无结果再按互链工单回退(只认互链单,余仍 403);bridge.message 对客结论(kind=conclusion 或缺省)在互链工单 source=email 时经发信腿(lib/bridge-email-leg.ts,callback route 注入 BridgeStore 可选方法 deliverTicketEmailReply)落工单公开评论+以 sendTicketReplyEmail 回首封来信地址(Re: 原主题、inReplyTo=首封 message_id)+回填 first_response_at,发信失败不回滚回推、内部评论留痕,腿未注入时降级只落线程;REQ-20261025-36 定版:工单锚会话(session.ticket_id 非空)的 bridge.evidence 证据种类按锚事件归属定——锚到互链工单(ticket.* 分派事件)允许 user_confirmation/server_recheck(与 assist.escalated 同口径,retest_result 拒),锚到会话自身协助事件走原二键表,非工单锚会话行为不变;锚会话关单/重开同轮同步互链 tkt 工单终态(resolved+resolved_at/重开回 open 清 resolved_at),同步失败只留痕不回滚会话、以新 agent_seq 重发同一 evidence 可重试同步

Events/api/bridge/eventsGET1 个接口

GET/api/bridge/events

GET /api/bridge/events — Agent pull 领活入口(REQ-20261025-06,设计 §13):无入站 API 的外部 agent(如客户侧 Support)主动领活,与 callback 同源 HMAC-SHA256 验签(X-Bridge-Signature,签名对象=原始查询字符串,5 分钟窗),无登录会话。query { claim?, limit? }:只回调用方名下的待领事件(delivery_status ∈ queued_no_endpoint/pending;按号过滤:工单事件按分派归属、协助事件归绑定 agent,未分派工单事件不进任何 pull;统一待办排序=渠道档→SLA 余量→FIFO),limit 默认 20、上限 50;claim=1 即领取——领取走带状态守卫的原子更新(并发不重复领,REQ-20261025-11 子集 A),返回批标 delivered+handler=support_agent(接单留痕),响应 { ok, paused, binding_missing, claimed, events: [出站信封(同投递 body,载荷已脱敏)] },claimed 以实际领取数计、events 只含实际领到的;ops 一键暂停 Support(任一侧状态非 active)时 paused:true 且不领取(只回自己名下清单);绑定解析不到/失败时 200+binding_missing:true+空清单(降级只读,不再 500);未配密钥 503 BRIDGE_NOT_CONFIGURED、验签失败 401 并落审计(不落任何状态变更)、555 未应用 503 BRIDGE_NOT_READY;REQ-20261025-11 子集 B 起同 callback 双验(Bearer agt_ 令牌优先、不依赖 HMAC secret 是否已配置),令牌路按令牌员工身份解析绑定(resolveAgentBinding)过滤与领取,handler 由归属派生(Support 恒 support_agent、其余 agent:<员工号小写>);事件归属判定切 agent_bridge_events.agent_id 列读法(563 落列+存量回填,空列行走 context_ref 旧口径兜底)

Tools/api/bridge/toolsPOST1 个接口

POST/api/bridge/tools

POST /api/bridge/tools — Scoped 工具生产调用入口+核验链接签发(REQ-20261026-01 工具生产接线线;设计 D29 §6.3/§12.1,P0 REVIEW P2-2 销账):桥的第三个动词,与 pull/callback 同源双验(Bearer agt_ 令牌身份为准/HMAC-SHA256 签名头、5 分钟窗),无登录会话。body { tool, ticket_id(工作锚:工单 id/聊天会话 id/桥会话 id), args?, agent_id?(只作一致性校验,与服务端解析身份不符 403 AGENT_ID_MISMATCH) }。ctx 由服务端按鉴权+锚上事实构造(岗位清单=agent_roles.tool_allowlist 与注册表取交集、模板显式空数组即空清单;模板未配时回退只限 Support 绑定本人(回 D29 §12.1 注册表全集),其余 platform 与全部 tenant 域不回退;chat 走会话快照 v2 的被分配权限键、email 走工单身份等级/线索组织/核验证据),body 自报的 scope/org/权限不读、伪造不生效(args 自带他组织 organization_id 当场 ORG_MISMATCH)。分派绑定两级:锚工单 assignee 或桥事件显式归属命中调用方才许调,未分派/他人单 403 NOT_ASSIGNED、工具不执行;且 args 指向的目标(工单/会话/附件/现场包)必须同属该锚的工作集,否则同样 NOT_ASSIGNED;tenant agent 锚组织≠档案组织 ORG_MISMATCH。tool 查表单一分发:session_context_get/ticket_identity_get/attachment_fetch/context_pack_get/context_pack_request(全经 executeScopedTool 交集入口+取行后组织二次校验,未注册名 NO_TOOL、无第二条取数通道);context_pack_request 的 reason 自由文本先过输出拦截(assist-output-guard,命中禁词整段丢弃只发定版卡,P1 review P2-3 落实)。动作 identity_verification_issue:给锚工单签发 L3 核验链接(lib/agent-verify-issue.ts:工单存在+owner_scope='platform' 守卫(P3-6,createIdentityVerification/verifyInApp 内层同守卫)+分派校验+绑定邮箱取工单首封发件地址;令牌只存 sha256、30 分钟、单次原子消费的 P0 口径不变;回执 verify_url 域名由服务端按请求 origin 拼、agent 不许自带域名)。每次调用恰好一条审计(结构化日志恒落+platform 绑定写穿 agent_work_logs;专用审计表未建,后续与 BYOA ai_agent_tool_calls 合并落点)。绑定解析不到 200+binding_missing:true;未配桥 503 BRIDGE_NOT_CONFIGURED、验签失败 401+审计、桥/身份/现场包表未就绪 503。**新端点入池,saas 路由净增 +1 文件,待域拆分 S0 腾位随批落地**

Inbound/api/bridge/inboundPOST1 个接口

POST/api/bridge/inbound/[adapter]

POST /api/bridge/inbound/[adapter] — push 适配层入站入口(REQ-20261025-11 子集 D,套件设计 §8.6):厂商平台 webhook 入站,无登录会话,验签在适配器内(首样本 Manus=RSA-SHA256,头 X-Webhook-Signature(base64)+X-Webhook-Timestamp(unix 秒),签名串 `${timestamp}.${rawBody}`,±300 秒窗;公钥走 ops 配置 env MANUS_WEBHOOK_PUBLIC_KEY,值不入仓)。处理链:适配器验签→厂商事件 id 去重(新表 agent_bridge_inbound_receipts,验签通过后才占位,(adapter_code, vendor_event_id) 唯一)→按出站回写的 adapter_ref 锚点归一为桥标准回推(task_stopped+finish→bridge.message、ask/task_deleted→bridge.handoff)→走既有 POST /api/bridge/callback 同一核心校验链(作用域/幂等/输出拦截不绕)。响应 outcomes:applied/duplicate(已终局事件的重放或重复投递,200 零双写;receipt 带处理状态,未终局——锚点未到/处理失败——的重投会重新处理,子集 D 窄修 569)/created_noted/ignored(未知类型或锚点缺失,200+审计,锚点缺失为可重试态);验签失败 401+审计+零状态变更且不落去重行;未知 adapter 404;桥表/去重未就绪 503 BRIDGE_NOT_READY。注册表三家+pull_only 占位(manus 接口级实现、grok/dust 占位恒拒、pull_only 纯登记);与出站推送(AGENT_BRIDGE_WEBHOOK_URL,deliverBridgeEvent)及 pull 通道(GET /api/bridge/events)互不影响;未接真实厂商账号(接口级就绪)

Clients8 个接口

Clients/api/clientsGETPOSTPATCHDELETE8 个接口

GET/api/clients

商户(Client)列表,按 code/name 模糊搜索、按是否启用过滤;组织隔离。

POST/api/clients

新建商户(code 同组织查重,code/name 必填);组织隔离,组织取登录上下文不信任客户端传入。

GET/api/clients/{id}

查询商户详情,同时返回其 Portal 用户明细(邮箱/显示名/成员状态)和关联仓库明细

PATCH/api/clients/{id}

更新商户(白名单字段,code 改了会查重;is_active 不能直接改,必须走启用/停用接口)

POST/api/clients/{id}/activate

启用商户;同时恢复其 Portal 用户的组织成员状态和登录权限(解 ban)

POST/api/clients/{id}/deactivate

停用商户;有未完成单据(销售单/入库单/出库单/RMA)且不传 force 时拒绝(409 HAS_OPEN_DOCS 并附单据清单);同时冻结其 Portal 用户(成员 suspended + auth ban)

DELETE/api/clients/{id}/portal-users

解绑商户的 Portal 登录用户;只从商户 portal_users 数组移除(不断 auth 用户、不删组织成员),可重新绑定

POST/api/clients/{id}/portal-users

给商户创建 Portal 登录用户(Merchant User):建 auth 用户 → 组织成员 → Merchant 角色绑定 → 追加到商户 portal_users

Connector Region1 个接口

Connector Region/api/connector-regionPOST1 个接口

POST/api/connector-region

POST /api/connector-region — 连接器区域打标 {table: channels

Cron73 个接口

Run/api/cron/runGET/POSTGETPOST67 个接口

POST/api/cron/run?task=admin-retention-sweep

保留期清理(Vercel Cron 每天凌晨 2 点调用),硬删除保留期到期的组织数据并清理过期导出临时文件

POST/api/cron/run?task=admin-export-worker

导出任务处理 worker(Vercel Cron 每分钟触发),逐表分块导出 CSV 到 R2,全完后打包 ZIP

GET/api/cron/run

定时任务统一分发入口(GET 形态):`?task=<name>` 查表分发到各任务 handler;本入口不做鉴权,鉴权委托各 task handler 自带 secret 校验;执行前过自动任务总开关闸门(关则 200 `{ ok:true, skipped:true, task }` no-op,开关表读失败 fail-open)。各任务分行见下方 `?task=` 行。

POST/api/cron/run

定时任务统一分发入口(POST 形态):同 GET 形态说明。

GET/api/cron/run?task=abc-analysis

ABC 分析定时扫表(外部 cron 每天调用,GET 也可手动触发),按各客户自己的间隔天数判断到期后跑 90 天出库量分析并更新商品 ABC 等级

POST/api/cron/run?task=abc-analysis

ABC 分析定时扫表(外部 cron 每天调用),按各客户自己的间隔天数判断到期后跑 90 天出库量分析并更新商品 ABC 等级

GET/api/cron/run?task=appointment-hold-release

POST|GET /api/cron/run?task=appointment-hold-release — 预约未确认占额释放(REQ-20261025-19 P1;cronSecretOk 鉴权,sys_cron_runs 落行;Vercel Cron 每 30 分钟):距申请时段 ≤ 组织 pending_hold_release_hours 仍未确认 → 置 hold_released_at 释放名额(预约不取消)并通知客户;48h 未处理只催仓库(站内通知 dedupeKey+催办邮件 escalated_at 原子打戳双防重,每单只催一次;客户改提后清戳可再催)

POST/api/cron/run?task=appointment-hold-release

同 GET 形态

GET/api/cron/run?task=appointment-inspection

POST|GET /api/cron/run?task=appointment-inspection — 预约闸口巡检(REQ-20261025-19 P3;cronSecretOk 鉴权,sys_cron_runs 落行;Vercel Cron 每 30 分钟):①NO_SHOW——CONFIRMED 预约过时段结束+迟到宽限仍无进场记录 → 条件更新置 NO_SHOW + 客户/承运商(站内+邮件)/仓库三方通知 + 未用令牌吊销;②自助待核验过期——PENDING_VERIFICATION 超过 min(提交+pending_verify_expire_hours, 当日结束) → 置 REJECTED(auto_expired) + 时间线 + 吊销 entry 令牌 + 司机短信。判定收口 lib/gate-checkin.ts

POST/api/cron/run?task=appointment-inspection

同 GET 形态

GET/api/cron/run?task=appointment-assignment-timeout

GET /api/cron/run?task=appointment-assignment-timeout — 预约指派响应超时扫描(REQ-20261025-19 P2;cronSecretOk 鉴权,sys_cron_runs 落行;Vercel Cron 每 30 分钟):offered 且 response_deadline 已过的指派行 → expired+清预约 current_assignment_id+吊销该指派 guest 令牌+按通知矩阵升级(carrier/仓库站内、客户知情面);按 (state, response_deadline) 索引小批量滚动,单轮上限 200

POST/api/cron/run?task=appointment-assignment-timeout

同 GET 形态

GET/api/cron/run?task=attend-daily-compute

考勤日报定时计算(REQ-20261031-71 批一 L-G05):自动发现已启用考勤的组织(已配考勤组或近 30 天有打卡),只算昨日日报;计算引擎与桌面手动计算共用同一实现,逐组织失败隔离、部分失败整轮记 failed;长时间未算的组织打结构化告警日志

POST/api/cron/run?task=attend-daily-compute

同 GET 形态(手动触发可带 ?date= 补算指定日期)

POST/api/cron/run?task=analytics-subscriptions-tick

Analytics 订阅中心投递调度器(外部 cron 每 10 分钟调用),扫描到点的订阅并生成内容发邮件

POST/api/cron/run?task=billing-drayage-overtime

Drayage 超期费日累计(每天 03:00 太平洋时间跑),在用箱按 demurrage/per_diem 口径日增量记 billing_events 并写免费期到期预警

POST/api/cron/run?task=drayage-tracking-sync

POST /api/cron/run?task=drayage-tracking-sync — Drayage 集装箱追踪定时同步(T1;每 30 分钟;逐组织上限 50 箱;无 key 时 connected:false 正常结束、不产模拟数据)

POST/api/cron/run?task=billing-monthly-settle

3PL Billing 月结(每天 02:30 太平洋时间跑),把上月及更早的未结算 billing_events 按生效费率表算金额并原子建 draft 发票

POST/api/cron/run?task=castlegate-inventory-sync

Wayfair CastleGate 库存定时同步(平台履约对接链第 4 环),全租户扫描 active 的 CastleGate 位置并写统一履约库存

GET/api/cron/run?task=drayage-voice-log-cleanup

清理 90 天前的 driver_voice_log 记录,防止无限增长

POST/api/cron/run?task=edi-tick

EDI 入站轮询,扫描已启用的 EDI 连接拉取 850 报文跑入站 pipeline,顺带重试到期的失败传输

GET/api/cron/run?task=employee-term-sweep

员工离职到期自动扫表(外部 cron 每天调用),把 term_date 已到期的在职档案置为 terminated 并释放账号绑定

POST/api/cron/run?task=employee-term-sweep

员工离职到期自动扫表(外部 cron 每天调用),把 term_date 已到期的在职档案置为 terminated 并释放账号绑定

GET/api/cron/run?task=cron-runs-watchdog

POST|GET /api/cron/run?task=cron-runs-watchdog — 定时任务留痕对账哨兵(REQ-20261103-05;cronSecretOk 鉴权;Vercel Cron 每天 06:40 UTC):按期望清单(lib/cron-tasks/cron-expectations.ts,与 vercel.json 调度对齐)逐件比对 sys_cron_runs 近 48h 落行与最近一行距今时长,超 maxGapMinutes 无新行=缺行;哨兵自身落行——有缺行 status=failed、error_message 以 MISSING_RUNS 点名、result_summary.detail 含逐件明细(近 48h 行数/最近一行/距今分钟/容忍上限/原因);只落库可查、不发外部通知;查库失败落 WATCHDOG_CHECK_ERROR failed 行并回 500

POST/api/cron/run?task=cron-runs-watchdog

同 GET 形态

POST/api/cron/run?task=fba-inventory-sync

Amazon FBA 库存定时同步(平台履约 P0),全租户扫描 active 的 FBA 位置,有 SP-API 凭证走真实接口、无凭证走模拟值

POST/api/cron/run?task=integration-tick

Integration 定时流程执行器,扫描到期的 schedule 流程并执行(总开关 INTEGRATION_ENABLED 默认关闭)

POST/api/cron/run?task=landed-cost-hts-sync

HTS 官方税率定时同步(每周一次),逐章节调 USITC 免费 API 解析 MFN 税率并 upsert 进数据库

GET/api/cron/run?task=labor-summary

Labor 小时汇总聚合(REQ-20261031-71 批一 L-G03):把效率事件按组织/仓库/人/类型/小时聚合写 labor_summary_hourly,回看近 3 小时重算;零时长事件整件不计入汇总;看板与 operators 改查汇总(当前小时以事件直读为准、不双计)

POST/api/cron/run?task=labor-summary

同 GET 形态

GET/api/cron/run?task=labor-recon

Labor 工时三账对账日算(L-G04,REQ-20261101-06;每日 10:30 UTC):滚动重算昨日+前日两日(America/Los_Angeles 日界;承接考勤日报迟生成的自愈——日报迟到时先落 R2a 形态、前日滚动重算自动修正);计算口径单一事实源在 DB 函数 labor_recon_run(迁移 744),本任务只做组织发现(范围内有考勤日报或有工时条目的组织)+逐组织调用,与页面手动重算共用同一函数;逐组织失败隔离,任一组织失败整轮记 failed 并带逐组织摘要,不被绿灯掩盖;幂等(同日重跑结果一致)

POST/api/cron/run?task=labor-recon

同 GET 形态

POST/api/cron/run?task=mygpt-tasks

MyGPT 定时任务执行器(外部 cron 每 5 分钟调用),扫描到期的任务逐个执行聊天、写运行记录并按需发邮件

POST/api/cron/run?task=rms-timeout

RMS 超时自动取消(每日跑),REQUESTED 超 3 天未审批或 APPROVED/LABEL_ISSUED 超期望归还日 10 天未寄回的工单自动取消

POST/api/cron/run?task=rms-storage-billing

POST /api/cron/run?task=rms-storage-billing — RMS 在制仓储日快照计费(RMS 二期包 2,每日跑前一业务日:超免租天数(默认 7,组织可配)的在制件数按货主汇总落 RMS-STORAGE-DAY 计费事件)

GET/api/cron/run?task=sequence-runner

CRM Sequence 执行器(每 15 分钟跑一次,GET 也可手动触发),做自动入组、推进到期步骤、自动退出检查(总开关默认关闭)

POST/api/cron/run?task=sequence-runner

CRM Sequence 执行器(每 15 分钟跑一次),做自动入组、推进到期步骤、自动退出检查(总开关默认关闭)

POST/api/cron/run?task=sfn-inventory-sync

Shopify SFN 履约库存定时同步(平台履约对接链第 3 环),全租户扫描 active 的 SFN 位置,有 Shopify 凭证走真实接口、无凭证走模拟值

GET/api/cron/run?task=sourcing-auto-pull

POST|GET /api/cron/run?task=sourcing-auto-pull — 货源自动拉品扫描(用户在连接上亲手开启的 auto_pull 设置:开关+每天/每周+每次上限;双形态 secret 鉴权+自动任务总开关闸门;Vercel Cron 每小时):分页扫连接、到期才按已配关键词拉品入选品池(只入池、绝不自动建品/上架),单连接报错(含 429)只停本连接并留痕 config.auto_pull_run

POST/api/cron/run?task=sourcing-auto-pull

同 GET 形态

GET/api/cron/run?task=promo-price-tick

POST|GET /api/cron/run?task=promo-price-tick — 促销限时调价扫描(REQ-20261031-46 批二;双形态 secret 鉴权+自动任务总开关闸门;Vercel Cron 每 15 分钟):依次跑到点激活(CAS 抢占→物化→快照算价→推价)、到期/停止恢复(按快照恢复、失败堵死 restoring 无限退避重试封顶 2h)、到期重试(推价失败 10 分钟起退避上限 5 次、冲突行补激活);真实 429 只停本组织本轮;模拟连接不调店铺 API、行标 simulated

POST/api/cron/run?task=promo-price-tick

同 GET 形态

POST/api/cron/run?task=tiktok-fbt-inventory-sync

TikTok Shop 履约库存定时同步(平台履约对接链第 2 环),全租户扫描 active 的 FBT 位置,有凭证走真实接口、无凭证走模拟值

GET/api/cron/run?task=tms-carrier-profile-refresh

承运商画像 nightly 刷新(每天 02:00 America/Los_Angeles 执行,GET 有 LA 时区门控,不到点直接 skipped)

POST/api/cron/run?task=tms-carrier-profile-refresh

承运商画像手动触发刷新(POST 不受 LA 时区门控限制),遍历全租户承运商重算画像并 upsert

POST/api/cron/run?task=wfs-inventory-sync

Walmart WFS 库存定时同步(平台履约对接 WFS 环),全租户扫描 active 的 WFS 位置,有凭证走真实接口、无凭证走模拟值

POST/api/cron/run?task=wms-abc-count-scan

WMS ABC 盘点定时扫描(每天 02:00),按商品 ABC 等级查到期未盘的(库位,商品),自动生成循环盘点任务

POST/api/cron/run?task=wms-replenishment-scan

WMS 补货定时扫描(每天 02:50),拣选位可用库存低于 min_qty 时自动生成补货任务

POST/api/cron/run?task=wms-visualization-snapshot

WMS 3D 可视化快照预计算(外部 cron 每 5 分钟调用),为有 published 布局的仓库按楼层算聚合写回快照表

GET/api/cron/run?task=wes-sla-watchdog

WES SLA 临期看门狗(WES 一期批 1-D,REQ-20261101-16,D83 §6.2;cronSecretOk 鉴权+自动任务总开关闸门,sys_cron_runs 逐组织落行;建议 Vercel Cron 每 5 分钟):扫描已释放(release_at 非空)未终态、due_at 进入临期窗(提前量读规则引擎 wms.picking 域码 W-K-D1,默认 60 分钟,含已超时)的任务,按单点排序键(due_at↑→priority↓→created_at↑)重排后逐条提醒——有负责人走任务到期提醒、无负责人提醒主管;同任务同 due_at 只提醒一次(step log `wes.sla.due_soon` 幂等键+通知 dedupeKey 双层去重,due_at 变更视为新一轮)。**只提醒不改派**(自动改派留三期)。

POST/api/cron/run?task=wes-sla-watchdog

同 GET 形态

GET/api/cron/run?task=wes-outbox-pump

WES 事件投递泵(WES 一期批 2-F,REQ-20261101-16,D83 §6.7;cronSecretOk 鉴权+自动任务总开关闸门,sys_cron_runs 落行;Vercel Cron 每分钟):先把 `wes_device_events` 的新 failed 事件桥接进内部 outbox(`wes_event_deliveries`,event_id=设备事件行 id、(event_id, consumer) 唯一键幂等),再投递到期投递行(退避 1m/5m/30m/2h/6h、6 次终态、单轮封顶 200 行分页)。订阅者按注册表+wiring 查表分发:一期就绪订阅者仅 `reroute`(M8 重路由);`orchestration-progress`、`notification-bridge` 为占位登记(ready=false,不产生投递行)。同入口即手动触发面。

POST/api/cron/run?task=wes-outbox-pump

同 GET 形态

GET/api/cron/run?task=wes-sim-tick

WES 模拟器节拍(WES 一期批 2-F,REQ-20261101-16,D83 §6.9;cronSecretOk 鉴权+自动任务总开关闸门,sys_cron_runs 落行;Vercel Cron 每分钟):云端模拟设备(devices.config.adapter_code 为已注册模拟适配器 sim_amr/sim_conveyor/sim_putwall)经 M6 同一通道领取设备 job 并推进一节拍,事件经同一 ingest 回流落 `wes_device_events`(run 标识在 payload 内);人工降级总开关开启的仓整轮跳过。同入口即手动触发面(演示即时推进一轮)。

POST/api/cron/run?task=wes-sim-tick

同 GET 形态

GET/api/cron/run?task=wes-offline-patrol

WES 设备离线判定巡检(WES 一期批 3-G,REQ-20261101-16,D83 §6.12 M12;cronSecretOk 鉴权+自动任务总开关闸门,sys_cron_runs 强制落行;Vercel Cron 每 5 分钟):逐组织扫 Hub 镜像设备,心跳新鲜度与 M5 超时 offline 读面归一口径对齐(阈值规则 `wms.wes` 域码 W-E-X2,缺省 5 分钟打印面先例);存量状态与有效状态不一致的设备只报警留痕(服务端日志+运行汇总),**不写 devices.status**。

POST/api/cron/run?task=wes-offline-patrol

同 GET 形态

GET/api/cron/run?task=wes-reconcile-patrol

WES 对账巡检(WES 一期批 3-G,REQ-20261101-16,D83 §6.12 M12;cronSecretOk 鉴权+自动任务总开关闸门,sys_cron_runs 强制落行;Vercel Cron 每小时):近 7 天挂 task 的 `wes_device_jobs` 与 `wms_task_step_log` 里程碑摘要行一致性(按 payload.job_id 精确匹配,job 状态要求的里程碑缺失即差异);差异只报警留痕,**不自动改数不补写**。单组织单轮 job 封顶 1000(超限 truncated 计数留痕)。

POST/api/cron/run?task=wes-reconcile-patrol

同 GET 形态

POST/api/cron/run?task=yms-visualization-snapshot

YMS 3D 堆场可视化快照预计算(外部 cron 每 5 分钟调用),为有 published 布局的堆场算整堆场聚合写回快照表

POST/api/cron/run?task=assist-verify

POST /api/cron/run?task=assist-verify — AI 辅助接入发版后批量复测(内部任务,x-cron-secret 鉴权):defect_filed 会话置 fix_deployed 后用原租户凭证复测,通过 verified、未过 verify_failed

POST/api/cron/run?task=bridge-retry

POST /api/cron/run?task=bridge-retry — 事件桥投递重试+SLA 督办(REQ-20261024-58,设计 §1.3/§6,内部任务,x-cron-secret 鉴权):到期出站事件按退避表(10s→1m→5m→30m→2h→6h)重投、耗尽进死信;T-50% 无首回推由平台模板补 diagnosing 状态(0 token),到 SLA 未关升级 needs_human;单轮各≤50 条;555 未应用回 BRIDGE_NOT_READY;REQ-20261025-10 起同入口加值班关段清扫(processDutySweep,套件设计 §7.3/§7.6):扫未结值班段(单轮≤100 段)——段主 agent 已被一键暂停→以 paused 关段(优先于闲置判定)、last_activity_at 超 5 分钟→以 idle_timeout 关段(agent 失联的僵尸段同路收口),关段带未结守卫与 agent 自退并发不双关。调度口径(2026-10-25 接泵修复):Vercel Cron `*/5 * * * *`(saas/vercel.json)自动触发,注册 caller='vercel',GET/POST 双注册(Vercel Cron 只发 GET),运行落行 sys_cron_runs(startCronRun/finishCronRun)供冒烟验收;此前 caller='manual' 无任何自动调度、生产从未被触发(实证 bridge-retry-verify)

GET/api/cron/run?task=oms-dispatch-auto-run

Vercel Cron 入口:自动扫描待分仓订单并执行分仓

POST/api/cron/run?task=oms-dispatch-auto-run

手动触发自动分仓:扫描本组织待分仓订单并下发出库单

POST/api/cron/run?task=tickets-email-worker

邮件轮询 worker:拉未读邮件去重后自动建单、关联单据、AI 分类并按规则自动回复/生成草稿(Vercel Cron 每 5 分钟调用,用 secret 鉴权);platform 配置开启 auto_assign_support(迁移 588)时平台新单自动分派 Support(REQ-20261025-36 余项,失败不阻断建单)

POST/api/cron/run?task=tickets-sla-worker

SLA 超时检查 worker:扫描快超时/已超时工单并升级通知(Vercel Cron 定时调用,用 secret 鉴权)

GET/POST/api/cron/run?task=wes-events-retention

设备事件留存清理 cron(批 2-E,D83 §6.6/§6.12):日级;wes_device_events 明细超 90 天先按 (组织,设备,事件码,小时) 滚存计数进 wes_device_event_hourly 再分批删除(每轮封顶 10 页×1,000 行)。cronSecretOk 鉴权+自动任务总开关闸+sys_cron_runs 强制落行。

Agent Scheduler/api/cron/agent-schedulerGETPOST2 个接口

GET/api/cron/agent-scheduler

通用 Agent 调度器(Vercel Cron 用 GET 触发,内部转调 POST 逻辑):扫到期的 agent_wakeups(最多 50/轮),平台 agent 本进程 LLM 处理、租户 agent 转调 SaaS 闹钟接口;支持 x-cron-secret 或 Authorization: Bearer 两种鉴权。

POST/api/cron/agent-scheduler

通用 Agent 调度器(外部 cron 每 2 分钟 POST 一次):扫到期的 agent_wakeups(最多 50/轮,原子占位防多实例抢单),平台 agent 本进程 LLM 处理、租户 agent 转调 SaaS 闹钟接口;鉴权用请求头 x-cron-secret 或 Authorization: Bearer。

Agent Runner/api/cron/agent-runnerPOST1 个接口

POST/api/cron/agent-runner

Proactive Agent 触发器扫描器(每轮扫启用的 agent 触发器,满足条件就建 run、按规则或 LLM 生成动作,低风险自动执行、高风险进审批队列);鉴权用请求头 x-cron-secret。

Query Learn/api/cron/query-learnPOST1 个接口

POST/api/cron/query-learn

Agent 主动学习(每天跑一次):把用户提问按归一化文本精确合并、再按向量余弦相似度 > 0.85 并入问题簇,被问 >=5 次且 >=2 个不同用户时生成 KB/能力补齐建议;鉴权用请求头 x-cron-secret。

Runs/api/cron/runsGET1 个接口

GET/api/cron/runs

本租户定时任务运行日志(租户鉴权,只返回本组织),支持任务名/状态/日期筛选与分页

Trial Reminders/api/cron/trial-remindersGET1 个接口

GET/api/cron/trial-reminders

试用到期前 30 天提醒(每天跑一次):读试用即将到期视图,逐条发提醒邮件,发送成功后才标记防重发;鉴权用 Authorization: Bearer <CRON_SECRET> 或 ?secret=。

Cron Runs1 个接口

Cron Runs/api/cron-runsGET1 个接口

GET/api/cron-runs

平台定时任务运行日志(全平台);平台员工鉴权(monitoring.view 权限)。

Customs27 个接口

Declarations/api/customs/declarationsGETPOSTPATCHDELETE19 个接口

GET/api/customs/declarations

报关单列表(类型/状态/客户/入库单/运单/关键字筛选,分页)

POST/api/customs/declarations

新建报关单(自动取号 CUS-000001,自动生成商业发票/装箱单/提单单证骨架)

GET/api/customs/declarations/{id}

报关单详情(含明细行/单证/ISF/查验/最新筛查)

PATCH/api/customs/declarations/{id}

编辑报关单(仅 draft/pending_submit;提交/放行/取消走专用端点)

POST/api/customs/declarations/{id}/calculate

按明细行计算关税/增值税/其他税,回写报关单与行级税额

POST/api/customs/declarations/{id}/cancel

撤回/取消报关单(draft/pending_submit/submitted → cancelled,不可逆)

POST/api/customs/declarations/{id}/complete

办结报关单(released → completed,写 completed_at)

GET/api/customs/declarations/{id}/documents

报关单证包列表(附必需单证缺失清单)

POST/api/customs/declarations/{id}/documents

关联/上传报关单证(按 doc_type upsert;支持 multipart 文件上传或 JSON 关联已有文档)

GET/api/customs/declarations/{id}/inspections

报关单查验记录(按查验日期倒序)

POST/api/customs/declarations/{id}/inspections

新增查验记录(submitted 自动转 inspecting;WMS 托盘调往查验区)

POST/api/customs/declarations/{id}/isf

ISF 申报(美国进口 10+2;仅 import 且状态为 submitted/inspecting/released)

GET/api/customs/declarations/{id}/lines

报关明细行列表(按 line_no 排序)

POST/api/customs/declarations/{id}/lines

新增报关明细行(仅 draft/pending_submit;自动算 total_price,回写报关单货值)

DELETE/api/customs/declarations/{id}/lines/{lineId}

删除报关明细行(仅 draft/pending_submit;回写报关单货值)

PATCH/api/customs/declarations/{id}/lines/{lineId}

编辑报关明细行(仅 draft/pending_submit;数量/单价变更自动重算)

POST/api/customs/declarations/{id}/release

放行报关单(submitted/inspecting → released;联动 TMS 运单推进)

POST/api/customs/declarations/{id}/screen

合规筛查(被筛查方与名单模糊比对,命中则提交被阻断)

POST/api/customs/declarations/{id}/submit

提交报关单(draft/pending_submit → submitted;校验明细/单证/筛查)

账单/api/customs/billsGETPOSTPATCH4 个接口

GET/api/customs/bills

费用账单列表(带客户名/报关单号,分页)

POST/api/customs/bills

新建费用账单(自动取号 FEE-000001;同一报关单只许一张)

GET/api/customs/bills/{id}

费用账单详情(含明细行)

PATCH/api/customs/bills/{id}

账单状态流转(draft→issued→paid;issued 时推送 Accounting 生成发票)

Hs Codes/api/customs/hs-codesGET2 个接口

GET/api/customs/hs-codes

HS 编码搜索(品名关键词 → 推荐编码 + 美/欧/中示例关税率)

GET/api/customs/hs-codes/history

历史归类查询(同一客户+相似品名 → 以前用过的 HS 编码,最近优先)

Inspections/api/customs/inspectionsGET1 个接口

GET/api/customs/inspections

组织内查验记录聚合列表(带报关单号,查验管理页用)

Isf/api/customs/isfPATCH1 个接口

PATCH/api/customs/isf/{id}

ISF 申报状态更新(not_filed→filed→accepted/rejected;rejected 可重报)

Demo Requests8 个接口

Demo Requests/api/demo-requestsGETPOSTPATCH8 个接口

GET/api/demo-requests

查 Demo Request 列表,支持状态筛选、关键词模糊搜索(客户名/公司/邮箱/单号)、按 agent 筛选,分页。

POST/api/demo-requests

平台员工手动创建 Demo Request;customer_name 必填;同一邮箱 7 天内已有 request/contacted 的会自动合并返回现有(不重复建)。

GET/api/demo-requests/{id}

查一条 Demo 申请的详情,含关联 agent 信息

PATCH/api/demo-requests/{id}

按状态机流转 Demo 状态(联系/约时间/开会/完成/放鸽子/归档等)

POST/api/demo-requests/{id}/cancel

取消 Demo(必填取消原因,已约时间的会提示需要发邮件通知客人)

POST/api/demo-requests/{id}/convert

把 Demo 申请一键转成 CRM 的 Lead(建公司+首个联系人,幂等)

POST/api/demo-requests/{id}/reactivate

重新激活已取消的 Demo(回到 request 状态,保留历史,SLA 重新计时)

POST/api/demo-requests/{id}/summary

提交 Demo 会议总结,自动完结 Demo(有关联 lead 会同步到 lead 备注)

Diagnostic Logs1 个接口

Diagnostic Logs/api/diagnostic-logsGET1 个接口

GET/api/diagnostic-logs

ops(admin 应用):连接诊断日志只读列表(平台员工 + monitoring.view;按 connector_code / connection_kind / ok / organization_id / connection_id / 时间范围筛选,分页)

Dock Recommendations3 个接口

Dock Recommendations/api/dock-recommendationsPOST1 个接口

POST/api/dock-recommendations

Dock 月台推荐(REQ-20261106-20 底座,D125 §11):入参只收 id 与上下文 {trigger*, appointment_id?, entry_id?, load_id?, receipt_id?, client_id?, warehouse_id?, yard_id?, direction?, window_start?, window_end?},服务端按 id 回查事实算推荐(回查优先、显式入参仅回落;亲和→距离→编码序+能力/时段硬过滤;送货主存区走 889 聚合 RPC),trigger 校验上下文(gate_checkin 须带 entry_id 或 appointment_id、appointment_confirm 须带 appointment_id,不满足 WMS_VALID_001 拒绝),端点层统一落 dock_recommendation_logs(10 分钟幂等);引擎异常回 200+none+error_code,不挡预约/签到;权限=登录+组织成员(设置类口径)

Logs/api/dock-recommendations/logsGET1 个接口

GET/api/dock-recommendations/logs

推荐回看与采纳率基础查询(D125 §8):?appointment_id=/entry_id= 取最近一条日志;无 id 时按 warehouse_id/area_code/trigger 聚合采纳率(每单据每 trigger 取最后一条已定案行)+日志分页(page_size 封顶 100)

Finalize/api/dock-recommendations/finalizePOST1 个接口

POST/api/dock-recommendations/finalize

推荐定案回写(REQ-20261106-20 门面批,D125 §8):{trigger*(appointment_confirm/appointment_assign/gate_checkin), appointment_id?/entry_id?(至少一个,无锚点回 WMS_VALID_001), final_dock_id*(必填键,可为 null=清空落位仍算定案), override_reason_code?, override_note?} → 把同 trigger 链最近一条未定案日志行一次性回填 final_dock_id/adopted/override_*(口径单点在 lib finalizeRecommendationLog:重复回填忽略、不覆盖已定案行);回写是留痕非业务前置——lib 抛错回 200+{updated:false},调用面吞错不挡预约保存/签到;权限=登录+组织成员

Driver3 个接口

预约/api/driver/appointmentsGETPOST3 个接口

GET/api/driver/appointments

司机端 — 我的预约指派(REQ-20261025-19 P2;登录 user → shared_drivers.user_id 解析司机档案,口径同 TMS 司机端):只回指派给本人的 assignment(offered/accepted+近期历史)+预约摘要(时段/仓库/单号)

POST/api/driver/appointments/{id}/respond

司机端 — 回应预约指派(REQ-20261025-19 P2):{action:'accept'

GET/api/driver/appointments/{id}/qr

司机端 — 到场核销 QR(REQ-20261025-19 P3):仅 state=accepted 的本人指派可取;appointment_driver 令牌按需签发/重显(已有活跃令牌由登记行重建同一串),过期 = 时段结束 + 迟到宽限,过窗回 410;回 token/expires_at/opens_at/closes_at/window_open_now

Email Intake1 个接口

Verify/api/email-intake/verifyGET1 个接口

GET/api/email-intake/verify

白名单邮箱确认落地(公开,token 即凭证):token 以 sha256 哈希比对,一次性消费,命中置 verified 并落审计。返回大白话 HTML 结果页。

Ext Apps10 个接口

Ext Apps/api/ext-appsGETPOSTPATCH8 个接口

GET/api/ext-apps

GET /api/ext-apps — 应用市场注册表 App 列表(ops 管理面全量口径:visibility/status/owner_org_id 过滤+有界分页;非租户目录面);staff 会话+tenants.view

GET/api/ext-apps/{id}

GET /api/ext-apps/{id} — App 详情:App 行+全部版本行(管理面口径);staff 会话+tenants.view

GET/api/ext-apps/{id}/versions

GET /api/ext-apps/{id}/versions — 该 App 的全部版本行(建行序);staff 会话+tenants.view

GET/api/ext-apps/{id}/versions/{versionId}

GET /api/ext-apps/{id}/versions/{versionId} — 版本行详情;?view=certification 时同回认证状态+审核记录(路由不直查认证表);staff+tenants.view

PATCH/api/ext-apps/{id}

PATCH /api/ext-apps/{id} — 改可见性和/或六语介绍 {visibility: private

PATCH/api/ext-apps/{id}/versions/{versionId}

PATCH /api/ext-apps/{id}/versions/{versionId} — 版本行三类改动(可同传):declaration 声明面(仅 draft/changes_requested 可改,certified 后 409 指引发新版)/rollout 灰度可见范围 {visible_to: all

POST/api/ext-apps

POST /api/ext-apps — 代录建 App(生而 private;转 listed 走 [id] PATCH 并过认证前置校验,不许建行即 listed);可带 description_i18n 六语介绍随建行落库;staff 会话+tenants.edit

POST/api/ext-apps/{id}/versions

POST /api/ext-apps/{id}/versions — 代录建版本行 {version*, artifact_hash?, api_min_version?, api_max_version?, webhook_endpoint?, embed_origins?, placements?, scopes?}:新行从 draft 起走认证状态机,同 App 同 version 重复建行 409;staff+tenants.edit

Governance/api/ext-apps/governanceGET1 个接口

GET/api/ext-apps/governance

GET /api/ext-apps/governance — 市场治理读面:?view=installations(跨 org 安装总览)

Partners/api/ext-apps/partnersGET1 个接口

GET/api/ext-apps/partners

GET /api/ext-apps/partners — 开发者伙伴主体列表(status 过滤+有界分页);?view=members&developer_account_id= 改回该主体 active 成员列表;staff+tenants.view

Fleet45 个接口

Fuel/api/fleet/fuelGETPOSTPATCHDELETE7 个接口

GET/api/fleet/fuel

加油记录列表,按车辆和时间范围过滤并分页

POST/api/fleet/fuel

新建加油记录:校验里程递增、自动算本段油耗 mpg、回写车辆表显里程、有司机档案自动回填司机

DELETE/api/fleet/fuel/{id}

删除一条加油记录,下一条记录的油耗 mpg 会重新计算

PATCH/api/fleet/fuel/{id}

编辑一条加油记录:改完重算本条和下一条的 mpg,里程仍需在相邻两条之间递增

GET/api/fleet/fuel/alerts

异常油耗告警:检测 MPG 突降和单次加油量异常的车辆(可按单辆车查)

GET/api/fleet/fuel/stats

单辆车油耗统计:总加油量/总金额/平均 MPG(油箱对油箱法)/累计里程 + 趋势序列

GET/api/fleet/fuel/vehicles

油耗模块车辆下拉数据:精简字段的车辆列表(手机加油录入选车用)

车辆/api/fleet/vehiclesGETPOSTPUTDELETE7 个接口

GET/api/fleet/vehicles

车队车辆列表:每辆附今日点检结果,enrich=1 时再附主要绑定司机和最紧急的证件提醒

POST/api/fleet/vehicles

新建车辆档案:车牌同车队去重,成功返回新建车辆(含车身二维码 qr_token)

DELETE/api/fleet/vehicles/{id}

车辆报废:软删除,状态置 retired,档案/证件/维修记录保留可查

GET/api/fleet/vehicles/{id}

车辆档案详情:含证件到期/保养到期/今日点检/绑定司机概览

PUT/api/fleet/vehicles/{id}

编辑车辆档案:状态走状态机校验,报废为终态不可逆

PUT/api/fleet/vehicles/{id}/odometer

更新车辆表显里程(加油/点检/日常更新里程都调这个口子),自动写更新时间

GET/api/fleet/vehicles/by-qr

扫码看车况:按车身二维码 token(或车辆 ID)返回车辆状态/证件到期/保养到期/今日点检/当前司机

Documents/api/fleet/documentsGETPOSTPUTDELETE5 个接口

GET/api/fleet/documents

车辆证件列表(按到期日排序),vehicle_id 必填

POST/api/fleet/documents

新建车辆证件:可直接传文件(multipart,服务端转存统一文档库),或传已上传的 document_id 登记

DELETE/api/fleet/documents/{id}

删除车辆证件登记(附件本身留在统一文档中心,不随证件删)

GET/api/fleet/documents/{id}

车辆证件详情(含车牌/品牌/型号展开)

PUT/api/fleet/documents/{id}

编辑车辆证件(换附件传 document_id,传空字符串解绑附件)

Maintenance/api/fleet/maintenanceGETPOST5 个接口

POST/api/fleet/maintenance/complete

保养做完登记:写保养记录并自动落账、更新排程推算下次到期、回写车辆里程

GET/api/fleet/maintenance/due

全车队保养到期清单:每车每排程一行,逾期/快到期/正常排序,未挂计划的车单独列出

GET/api/fleet/maintenance/plans

某车辆类型的保养计划模板列表(含种子计划 + 自定义)

POST/api/fleet/maintenance/plans

新建自定义保养计划(按车辆类型命名空间,名称组织内唯一)

POST/api/fleet/maintenance/schedules

给一辆车挂保养计划:没有计划时先种子模板,缺的排程逐条插入(已存在的跳过)

Costs/api/fleet/costsGETPOST4 个接口

GET/api/fleet/costs/{vehicle_id}

单辆车多月成本趋势:每月油费/维修费/保险费/里程/每英里成本,缺月份自动补零行

GET/api/fleet/costs/compare

当月车辆成本榜单:花钱最多的 5 辆和最省钱的 5 辆(全月零花费的车不上榜)

POST/api/fleet/costs/recalculate

重新汇总某月全车队成本并幂等写入汇总表(重复调用覆盖同一行,可放心重跑)

GET/api/fleet/costs/summary

全车队当月成本汇总表(读汇总表;computed=false 说明本月还没跑过汇总,先调 recalculate)

Inspections/api/fleet/inspectionsGETPOST4 个接口

GET/api/fleet/inspections

车队 DVIR 点检记录列表:按车辆/类型/结果/日期过滤并分页

POST/api/fleet/inspections

提交一次 DVIR 点检:全部检查项必须作答;不合格自动建维修工单,关键项不合格还会锁定车辆进维修状态

GET/api/fleet/inspections/{id}

点检单明细:每项检查结果/照片/备注,以及车辆和关联维修工单信息

GET/api/fleet/inspections/templates

DVIR 点检模板及检查项:没有模板时自动建默认模板

工单/api/fleet/work-ordersGETPOST4 个接口

GET/api/fleet/work-orders

维修工单列表:按车辆/工单状态/关键词过滤并分页(id 可为维修单 id 或工单 id)

POST/api/fleet/work-orders

新建维修工单:写工单 + 车辆关联,并把车辆置为维修中;手机端可传文件直接上报故障

GET/api/fleet/work-orders/{id}

维修单详情:工单本体(含评论/附件)+ 车辆关联 + 车辆信息(id 可为维修单 id 或工单 id)

POST/api/fleet/work-orders/{id}/complete

维修完工验收:费用落定、工单关闭、车辆恢复在用;已验收重复调会 400

调度/api/fleet/dispatchGETPOST3 个接口

POST/api/fleet/dispatch/assign

TMS/Drayage/YMS 派单:校验车辆在用、写派单日志,传司机时同步更新人车绑定

GET/api/fleet/dispatch/available-vehicles

派单用可派车辆列表:只含在用状态的车,每辆带当前主要绑定司机和位置(尽力获取)

POST/api/fleet/dispatch/complete

完单回传:定位派单记录,回写表显里程(只增不减)、把本次行驶里程记入当月成本汇总,关闭派单

司机/api/fleet/driverGETPOST2 个接口

POST/api/fleet/driver/claim-vehicle

人车绑定:司机选择"我开这辆车",只能绑在用状态的车,旧绑定自动解绑保留历史

GET/api/fleet/driver/my-vehicle

当前登录司机的绑定车辆:含证件到期、保养到期、今日点检和司机信息概览,未绑定返回 vehicle:null

Dashboard/api/fleet/dashboardGET1 个接口

GET/api/fleet/dashboard

车队总览 dashboard 聚合数据:车辆状态分布、保养到期、未结维修工单、证件到期、今日点检、油耗、维修费、最新工单和点检异常

Fuel Logs/api/fleet/fuel-logsPOST1 个接口

POST/api/fleet/fuel-logs

记录一次加油(司机手机端简化接口,不做 mpg 计算)

Reminders/api/fleet/remindersGET1 个接口

GET/api/fleet/reminders

提醒中心:进入提醒期的证件列表按紧急度排序;type=maintenance 返回保养到期接口的跳转指引

供应商/api/fleet/vendorsGET1 个接口

GET/api/fleet/vendors

维修厂/供应商下拉数据源(取自 Master Data shared_vendors,只看启用的)

Guest5 个接口

门岗/api/guest/gateGETPOST3 个接口

GET/api/guest/gate

免登录 guest — 仓库入口自助登记(REQ-20261025-19 P3):?token= 验 warehouse_entry 入口令牌(版本制、只带 org+warehouse、非凭证)→ 发无状态自助会话(HMAC、绑 org+warehouse、2h)+ 仓库名与策略提示(phone_verify/walkin);?status_token= 凭 self_checkin 令牌查本人登记状态(只回 entry_no/status/reject_reason/dock_spot 非敏感字段)

POST/api/guest/gate

免登录 guest — 自助登记动作(凭自助会话):action=match 预约匹配探针(只回是否匹配+时段)/ otp_send / otp_verify(手机号 OTP,哈希落 gate_phone_verifications、60 秒节流、5 次上限)/ submit 提交自助登记(策略闸 walk-in 与 OTP、必填与必拍校验、(仓,车牌,当日) 去重、建 PENDING_VERIFICATION entry 并签 self_checkin 令牌+6 位短码;动作收口 lib/gate-checkin.ts)

POST/api/guest/gate/photo

免登录 guest — 自助登记照片先传(multipart:session+label(driver/vehicle/equipment/seal)+file ≤10MB):凭自助会话授权,服务端直调统一文档中心 lib 落 documents 表,回稳定路径 /api/documents/{id}/download?disposition=inline,与 entries photos 同口径

预约/api/guest/appointmentsGETPOST2 个接口

GET/api/guest/appointments

免登录 guest — 预约派车兜底(REQ-20261025-19 P2,不鉴权凭 gate 签名令牌):?token= 验签+查登记(未过期/未 used/未 revoked,fail-closed)后只回令牌绑定的那一张预约上下文(carrier_guest 附本 carrier 司机名单的脱敏字段;driver_guest 附本人指派快照);令牌格式与登记见 lib/gate-tokens.ts

POST/api/guest/appointments

免登录 guest 动作(REQ-20261025-19 P2):carrier_guest + action=assign(给本单指派司机,成功后令牌核销)/ driver_guest + action=accept 或 reject(reason 必填,成功后令牌核销);只给动作不给列表,guest 看不到任何他单数据

Internal1 个接口

Agent Tools/api/internal/agent-toolsPOST1 个接口

POST/api/internal/agent-tools/oms/sales-order-drafts

OMS 域内部执行端点(apps/oms,仅服务端):为 Rollie 创建一张销售单草稿。不是公开 API——只接受 core 网关签发的短时执行信封,不接受浏览器会话直调(无信封/错签/过期一律拒);公开 `POST /api/oms/orders` 的契约与行为不改。

Knowledge30 个接口

Bases/api/knowledge/basesGETPOSTPATCHDELETE5 个接口

GET/api/knowledge/bases

知识库列表,按可见范围过滤

POST/api/knowledge/bases

新建知识库

DELETE/api/knowledge/bases/{id}

归档知识库(不是物理删除,文档和 chunk 保留可恢复)

GET/api/knowledge/bases/{id}

取单个知识库详情(不可见按 404 处理)

PATCH/api/knowledge/bases/{id}

更新知识库(改名/改描述/改切分参数/归档|恢复)

Documents/api/knowledge/documentsGETPOSTDELETE5 个接口

GET/api/knowledge/documents

查某文档的知识库归属,或查某知识库下的文档列表

POST/api/knowledge/documents

把文档加入知识库,加入后自动投递索引任务

DELETE/api/knowledge/documents/{id}

把文档移出知识库,chunk 同步删除,原文不动

POST/api/knowledge/documents/{id}/reindex

重试失败或手动更新版本,版本号+1 后重新投递索引任务

GET/api/knowledge/documents/{id}/status

轮询文档索引状态,processing 超 30 分钟自动判失败

Categories/api/knowledge/categoriesGETPOSTPATCHDELETE4 个接口

GET/api/knowledge/categories

知识库分类列表,树形结构返回

POST/api/knowledge/categories

新建知识库分类

DELETE/api/knowledge/categories/{id}

删除分类,子分类级联删除,挂载文档的分类置空

PATCH/api/knowledge/categories/{id}

重命名/排序/移动分类(改 parent_id 可连子树整体移动,防循环)

Chunks/api/knowledge/chunksGETPOSTPATCH4 个接口

GET/api/knowledge/chunks

文档切分 chunk 列表(切分预览与管理,不返回 embedding 向量)

GET/api/knowledge/chunks/{id}

取单个 chunk 详情

PATCH/api/knowledge/chunks/{id}

手动干预 chunk(改内容/小节标题/启用开关),改内容会自动重做 embedding

POST/api/knowledge/chunks/merge

合并相邻 chunk,保留序号最小的行,其余删除,合并后重做 embedding

Platform Kb/api/knowledge/platform-kbGET4 个接口

GET/api/knowledge/platform-kb/articles

平台知识文章列表(租户只读)

GET/api/knowledge/platform-kb/articles/{slug}

平台知识文章详情(租户只读)

GET/api/knowledge/platform-kb/categories

平台知识分类列表(租户只读)

GET/api/knowledge/platform-kb/docs/{documentId}/download

下载平台知识文章的附件(租户只读,返回文件二进制流)

Feedback/api/knowledge/feedbackGETPOSTPATCH3 个接口

GET/api/knowledge/feedback

检索反馈队列,👎 优先按创建时间倒序

POST/api/knowledge/feedback

提交检索反馈(对某次问答点赞/点踩)

PATCH/api/knowledge/feedback/{id}

处理反馈(标记已修/不修),自动记录处理人

Tags/api/knowledge/tagsGETPOST2 个接口

GET/api/knowledge/tags

知识标签列表(租户级),支持模糊搜索

POST/api/knowledge/tags

新建知识标签,同名直接返回已有(幂等)

Process/api/knowledge/processPOST1 个接口

POST/api/knowledge/process

索引任务触发端口,扫 pending 文档执行提取→切分→embedding(供外部 cron 兜底调用)

Search Test/api/knowledge/search-testPOST1 个接口

POST/api/knowledge/search-test

检索测试(管理视角),支持向量/全文两种模式,只返回用户可见的结果

Stats/api/knowledge/statsGET1 个接口

GET/api/knowledge/stats

知识库统计看板(文档/chunk/反馈/token 汇总)

Lib1 个接口

Wecom Tickets.Ts/(服务层,无独立端点)`saas/lib/wecom-tickets.ts—1 个接口

—(服务层,无独立端点)`saas/lib/wecom-tickets.ts

企微渠道服务(T18/D50):绑定码签发/赎回(门户一次性码、只存哈希、赎回条件认领原子单次)与员工确认绑定 `staffConfirmWecomBinding`(verified_via=staff_confirm、操作人留痕)、模板发送(available_pickup / lfd_reminder / appointment_result 三类,内容取 T1 追踪与 T16 预约回写真实字段、无时间戳不发、48h 窗口以平台发送时刻为锚、窗口外 skipped_window、未绑定 skipped_unbound、全程 tkt_wecom_send_log 幂等留痕)、对客回复(绑定成败/未绑定引导/升级确认四话术经 kf 回发)、内部成员应用消息提醒(升级/窗口外/未绑定触发)。AI 注册表口径:本线**不新增 AI 工具**——已绑定会话的柜状态答复复用 T17 scoped 工具(customer_query_drayage_container 等)按工单 client_id 生成,企微只是传输渠道

Marketing6 个接口

Campaigns/api/marketing/campaignsGETPOSTPATCHDELETE5 个接口

GET/api/marketing/campaigns

查营销活动(Campaign)列表,支持按状态/类型/关键字筛选

POST/api/marketing/campaigns

创建一个营销活动(Campaign)

DELETE/api/marketing/campaigns/{id}

删除一条营销活动

GET/api/marketing/campaigns/{id}

查一条营销活动的详情(含发送/打开/点击/转化统计)

PATCH/api/marketing/campaigns/{id}

更新营销活动(只传 status 时做状态流转,否则按 CampaignInput 更新字段)

Promo Codes/api/marketing/promo-codesGET1 个接口

GET/api/marketing/promo-codes

查优惠码列表(给 Campaign 表单的下拉框用)。每条为完整 PromoCode 对象,含 `brandScope`(应用平台:all/docklify/orderball,565 / D22 加法字段;与 `appliesTo` 计费项维度正交)

Master Data18 个接口

Carrier Mappings/api/master-data/carrier-mappingsGETPOSTPATCHDELETE6 个接口

GET/api/master-data/carrier-mappings

查询承运商映射列表(渠道侧 carrier/service 文本 ↔ 内部标准 carrier_code/service_code),支持分页和筛选

POST/api/master-data/carrier-mappings

新建承运商映射(渠道侧 carrier/service 文本映射到内部标准 carrier_code/service_code)

GET/api/master-data/carrier-mappings?mode=seen

GET /api/master-data/carrier-mappings?mode=seen — Seen-but-not-mapped 派生视图(REQ-20261030-23,设计 D70 §5.3,不新增路由):近 30 天订单 channel_carrier/channel_service 原文按 (connection_id, carrier, service) 聚合,剔除已被三层映射命中的组合,回 order_count/last_seen_at/channel_code;分页 .range(1000) 封顶 20 页、超限回 truncated 标记。POST 同端点放宽:channel_carrier 可空(service 单独成键,存 '')。

DELETE/api/master-data/carrier-mappings/{id}

删除承运商映射

GET/api/master-data/carrier-mappings/{id}

查询单个承运商映射详情

PATCH/api/master-data/carrier-mappings/{id}

更新承运商映射(按传参局部更新,空串字段报错)

Carrier Users/api/master-data/carrier-usersGETPOSTPATCHDELETE5 个接口

GET/api/master-data/carrier-users

查询承运商登录账号(Carrier Portal 用户)列表,组织隔离,每项附承运商名称

POST/api/master-data/carrier-users

新建承运商登录账号(邮箱归一化小写,同组织承运商校验归属)

DELETE/api/master-data/carrier-users/{id}

删除承运商登录账号

GET/api/master-data/carrier-users/{id}

查询单个承运商登录账号详情

PATCH/api/master-data/carrier-users/{id}

更新承运商登录账号(换承运商/改邮箱/姓名/启用状态,按传参局部更新)

Rate Shopping Service Groups/api/master-data/rate-shopping-service-groupsGETPOSTPATCHDELETE4 个接口

GET/api/master-data/rate-shopping-service-groups

比价服务组列表(REQ-20261028-11):返回本组织的有效视图——同一锚点(内部 Carrier+Service)上,租户自建/覆盖组整组优先于平台预置组;附平台预置锚点清单(供 Carrier Service Mappings 页与选择器并入 AnyCarrier 等虚拟承运商)与成员目录(组编辑弹窗的服务清单数据源)。平台预置行对所有组织只读

POST/api/master-data/rate-shopping-service-groups

新建本组织的比价服务组(REQ-20261028-11):锚点=内部 Carrier+Service;成员随组头一次提交、整组单事务写入。锚点与平台预置相同时即「复制为我的覆盖」。同一锚点已有本组织组时回 409(`RS_GROUP_ANCHOR_DUPLICATED`,文案带已有组名),不产生第二行。**组只锚虚拟服务(Andy 2026-10-29 收紧定版)**:锚点承运商必须为虚拟承运商(anycarrier 或 shared_carriers.is_virtual=true,服务端 deriveAnchorIsVirtual 推导、不信客户端),非虚拟回 400 `RS_GROUP_ANCHOR_NOT_VIRTUAL` 大白话并指路 Carrier Service Mappings(先把渠道服务映射成虚拟服务再建组)

PATCH/api/master-data/rate-shopping-service-groups/{id}

整组更新本组织的比价服务组(REQ-20261028-11):与 POST 同一份完整入参(锚点+成员恒必填),组头与成员整组替换(单事务)——本接口是「全量提交」语义,没有部分更新。 id 为平台预置行时回 403(`RS_GROUP_PLATFORM_READONLY`,请先复制为我的覆盖);id 属其他组织按 404 处理。**组只锚虚拟服务(2026-10-29 定版)**:锚点非虚拟时保存为启用态回 400 `RS_GROUP_ANCHOR_NOT_VIRTUAL`;仅停用(is_active=false)存量真实锚组放行(整改动作)。引擎侧对存量真实锚组一律不予命中(resolveServiceGroup 按无组处理并留痕)

DELETE/api/master-data/rate-shopping-service-groups/{id}

删除本组织的比价服务组(REQ-20261028-11):成员随组头级联删除;同锚点存在平台预置组时,删后自动恢复平台预置生效。 id 为平台预置行回 403(`RS_GROUP_PLATFORM_READONLY`);属其他组织按 404 处理

Rate Shopping Policies/api/master-data/rate-shopping-policiesGETPOSTDELETE3 个接口

GET/api/master-data/rate-shopping-policies

运费比价设置列表(REQ-20261027-17):本组织启用中的政策行,按更新时间倒序;`?resolve=1` 时走共享解析器单一入口返回生效预览(不重写解析逻辑)

POST/api/master-data/rate-shopping-policies

按三级范围键 upsert 运费比价设置(REQ-20261027-17):同一范围(全租户/客户/客户+渠道)再次保存更新原行不重复;`action=delete` 时走删除。账号须为本组织且 connection_status 非空(名录账号拒绝并给人话报错);渠道须带客户

DELETE/api/master-data/rate-shopping-policies

删除一条运费比价设置(REQ-20261027-17):id 可放 `?id=` 查询参数或 body;不存在回 404

Me1 个接口

Orgs/api/me/orgsGET1 个接口

GET/api/me/orgs

当前登录用户有 active 成员资格的组织列表,供前端初始化当前组织

Mobile1 个接口

Issues/api/mobile/issuesPOST1 个接口

POST/api/mobile/issues

手机端各 App 通用的"问题上报",表单提交(描述和照片至少填一个),照片自动归档到统一文档中心

Notifications7 个接口

Notifications/api/notificationsGETPOST3 个接口

GET/api/notifications

当前登录用户的通知列表(按 created_at 倒序,分页;支持只看未读)。

POST/api/notifications

手动发送一条通知(收件人二选一:司机 driver_id 或用户 user_id)。

POST/api/notifications/{id}/read

把一条通知标为已读,只能标自己的(组织+收件人双重校验)

Preferences/api/notifications/preferencesGETPUT2 个接口

GET/api/notifications/preferences

查我的通知设置:16 个通知类型逐条列出"我开没开、短信开没开、能不能关"(设置页数据源;没设过的按注册表默认值显示,urgent 类 `enabled` 恒为 true、`canDisable=false`)。

PUT/api/notifications/preferences

改我对某一个通知类型的开关(站内开关和/或短信开关,传哪个改哪个,未传的保持原值——merge 语义)。urgent 类(任务超时/拣货缺货/短发确认)不许关站内开关,传 `enabled:false` 返回 400。

Unread Count/api/notifications/unread-countGET1 个接口

GET/api/notifications/unread-count

当前用户未读通知数,手机端红点用

Mark All Read/api/notifications/mark-all-readPOST1 个接口

POST/api/notifications/mark-all-read

把我全部未读通知一次标已读(通知页"全部已读"按钮用;只影响当前用户在本组织的通知)。

Ops2 个接口

Device Diag/api/ops/device-diagGET1 个接口

GET/api/ops/device-diag

GET /api/ops/device-diag — ops 设备诊断时间线(平台侧全量错误时间线,跨组织读 device_diag_events):参数 organization_id*、device_id、hours(1..720,默认 24);平台员工会话(只读排障)

Users/api/ops/usersPOST1 个接口

POST/api/ops/users/{userId}/unlink-identity

客服代解绑登录方式(ops 平台端,REQ-20261027-05 P1):平台员工登录+`support.impersonate` 能力(与代登录同级);body `{ provider(必填、≠email), reason(必填、≤500、入审计), organizationId(必填,服务端核验目标用户为该组织 active 成员) }`;执行走服务端会话代理(GoTrue 无 Admin 删单个 identity 的端点——设计稿附记二 §0 定案);解绑后将无任何登录方式时服务端硬拦 409 `no_signin_method_left`;项目未开 Manual Linking 回 422 `manual_linking_disabled`;成功写审计 `identity.unlinked_by_support`(after 记被解绑邮箱,不记任何 token)。租户详情页成员区有对应查看面+解绑弹窗。

Orderball32 个接口

Ledger/api/orderball/ledgerGETPOSTPATCH20 个接口

GET/api/orderball/ledger/summary

轻账本汇总(Money 页头 + Dashboard 待结算数据源):receivables/payables 各 {open_total, open_count, overdue_total, overdue_count, due_next_7d_total, due_next_7d_count, by_currency[]} + by_store 应收按店铺(渠道)拆解 + cash {received_this_month, paid_this_month} + unposted_count 漏记自查计数(D10 §6.4,附 unposted_known)。

GET/api/orderball/ledger/receivables

Orderball 轻账本应收列表(REQ-20261024-55,设计 docs/orderball-ledger-design.md D10 §5.1;migration 553 待应用,未应用回 503 LEDGER_NOT_READY)。默认 due_date 升序;status=overdue 为读时派生(open/partial 且 due_date<今日),all_open=open+partial。鉴权:组织成员(withWms 会话+组织归属)。

POST/api/orderball/ledger/receivables

手工建应收(T5)。入参:counterparty_name*、gross_amount*、currency、issue_date、due_date(缺省入账日+14 天)、counterparty_type、channel_id、notes。回 201 + 单据 DTO(entry_no 为 OBR- 前缀)。

GET/api/orderball/ledger/receivables/{id}

应收详情:单据 DTO + 核销历史 allocations(含 reversed 行)+ 来源订单摘要 source_order。

PATCH/api/orderball/ledger/receivables/{id}

只改 due_date / notes(金额与状态不许直改,D10 §5.1 白名单)。

POST/api/orderball/ledger/receivables/{id}/void

作废应收:仅从未有 active 核销时可作废;有核销回 LEDGER_ENTRY_HAS_ALLOCATIONS(先撤销核销再作废)。自动入账单作废后来源唯一键仍占用,不会被自动重建。

GET/api/orderball/ledger/payables

应付列表(与应收同构):status/channel 改 vendor_id 筛选;q 搜 entry_no/source_no/po_no/对方名。行含 amount/amount_paid/amount_adjusted/balance/po_no。

POST/api/orderball/ledger/payables

手工建应付(T5)。入参:counterparty_name*、amount*、currency、issue_date、due_date(缺省 +30 天)、vendor_id、notes。entry_no 为 OBA- 前缀。

GET/api/orderball/ledger/payables/{id}

应付详情:单据 DTO + 核销历史 + 采购单摘要 purchase_order。

PATCH/api/orderball/ledger/payables/{id}

只改 due_date / notes。

POST/api/orderball/ledger/payables/{id}/void

作废应付(条件同应收作废)。

GET/api/orderball/ledger/payments

收付流水列表:direction(in/out)/status/q(payment_no/reference/对方名)筛选,行带 unallocated_amount(未核销余额)。

POST/api/orderball/ledger/payments

登记收付 + 一次核销(D10 §5.3 核心端点):一次带 allocations[](分到哪几张单)与 adjustments[](fee/refund/discount/write_off,notes 必填)完成建流水→写核销→重算单据状态。direction=in 只能核销应收、out 只能核销应付;币种以首张目标单为准、其余须同币种;守恒校验不过整笔拒绝。source_type=platform_settlement 时按 (org, reference) 防重,重复登记幂等回既有流水(duplicated=true,200)。

GET/api/orderball/ledger/payments/{id}

流水详情 + 其核销明细(含 reversed)。

POST/api/orderball/ledger/payments/{id}/void

作废流水:先逐笔撤销其全部 active 现金核销(留 reversed 行)并重算受影响单据,再置 void;已同步外部的单据链接置 needs_attention。

POST/api/orderball/ledger/allocations

对既有流水补现金核销({payment_id, receivable_id|payable_id, kind:'cash', amount})或对单据补非现金调整({receivable_id|payable_id, kind: fee|refund|discount|write_off, amount, notes*})。同 (payment, 单据) 已有 active 现金核销时幂等返回既有行。

POST/api/orderball/ledger/allocations/{id}/reverse

撤销一笔核销:行置 reversed 不物理删,流水与单据累计按 active 行重算、状态回退;单据已同步外部时链接置 needs_attention。

POST/api/orderball/ledger/backfill

漏记补记(D10 §6.4):扫描已 fulfilled 无应收的订单与已收货完成(采购)无应付的入库单,逐个调同一幂等记账函数补齐(单轮上限 200),回 {posted_orders, posted_receipts, failed_orders, failed_receipts, errors}(失败计数与 posted 分开报,errors 为前 5 条 {scope,id,code,message} 样本;2026-10-24 D2 修复后口径,此前 ok:false 被吞只报 posted)。**2026-11-01 增第三段(REQ-20261101-16,D10 §3.5/T6)**:同轮再扫本组织 refund_status='done' 的 RMA(单轮上限 200),逐个调 `postRefundForRma` 补记退款冲减(幂等、业务键 `rma-refund:<rma_id>`),响应新增 posted_refunds / failed_refunds 计数,errors 样本 scope='rma_refund';退款实时入账的两条触发路径(退款结论动作、渠道 refunded 事件)与本段共用同一函数,重复调用返回 REFUND_ALREADY_POSTED 跳过不重记。

GET/api/orderball/ledger/sync

QBO/Xero 同步口状态(D10 §7 预留呈现):ob_ledger_sync_links 列表(provider/status 筛选)+ 各 provider 连接状态 connections + push_enabled=false(连接器待真实验证,不假装推送)。

POST/api/orderball/ledger/sync

登记待同步链接:仅当该 provider 已有连接时,为未建链接的本地单据(receivable/payable/payment)落 pending 链接行(唯一约束占位防重复推送);回 {connected, created, push_executed:false}。未连接回 connected=false、created=0。

库存/api/orderball/inventoryGETPOSTPATCH12 个接口

GET/api/orderball/inventory/warehouses

Orderball 仓库列表(含作业模式 operation_mode:simple=简易仓/full=完整仓;migration 551 加列,默认 full,与既有 ops_mode 不同概念)。PATCH 同路径设置 operation_mode。鉴权:组织成员(withWms)。

PATCH/api/orderball/inventory/warehouses

设置仓库作业模式 operation_mode(simple/full)。鉴权:组织成员(withWms)。REQ-20261024-49。

GET/api/orderball/inventory/bindings

Orderball 一品一位绑定清单:每个产品最多绑一个 picking 库位(一个库位可放多品),分页返回,附库位编码/类型、追踪标记与补货点(reorder_point)。鉴权:组织成员。

POST/api/orderball/inventory/bindings

一品一位绑定/改绑/解绑。目标必须是启用中的 picking 库位(DB 枚举 pick);目标仓有进行中盘点单时拦截改绑。location_id 传 null 为解绑。

POST/api/orderball/inventory/pick-record

Orderball 实拣回录扣账:从产品绑定库位扣减实拣数(短拣按实拣),批次品按 FEFO(有到期日)/FIFO(无到期日)逐批扣并同步批次在手量,序列号品逐个登记校验;写台账(transaction_type=pick,reference_type=orderball_pick)并同步库存明细切片;提交前按台账行键复核已录量防重复扣;盘点锁仓期拦截。

GET/api/orderball/inventory/pick-recorded

Orderball 按单已回录量(query `order_id`):台账行键(reference_type=orderball_pick+reference_id)的 \

GET/api/orderball/inventory/counts

Orderball 全仓盘点单列表(轻形态,不建 WMS 任务)。POST 同路径生成盘点单:按仓库余额+明细快照成行并锁仓(同仓只许一张进行中单)。

POST/api/orderball/inventory/counts

新建盘点单(明盘:账面数打印在清单上)。鉴权:组织成员(withWms)。REQ-20261024-49。

GET/api/orderball/inventory/counts/{id}

盘点单详情:行按库位编码排序(与纸质清单同序同列),含账面/实盘/差异;行数超 5000 标 lines_truncated。

POST/api/orderball/inventory/counts/{id}/enter

实盘批量回录(覆盖式,可纠错重提;只写实盘/差异、不过账)。单非 open 状态拒绝。

POST/api/orderball/inventory/counts/{id}/confirm

差异确认过账:未填实盘的行按账面计(回 kept_book_lines 明示);差异行写台账(transaction_type=count,reference_type=orderball_count,原因码 found/lost)并同步明细切片;已落账差异按台账行键复核只补未落(可安全重跑);关单并解锁。

POST/api/orderball/inventory/counts/{id}/cancel

取消盘点单并解锁(不落账,实盘数留痕)。单非 open 状态拒绝(COUNT_NOT_OPEN)。

Platform Agents3 个接口

Inbound Email/api/platform-agents/inbound-emailPOST1 个接口

POST/api/platform-agents/inbound-email

接收 Cloudflare Email Worker 转发的任务邮件并触发 agent 处理(凭 worker 密钥认证)

Sop Tag/api/platform-agents/sop-tagPOST1 个接口

POST/api/platform-agents/sop-tag

给 SOP 文档打上适用的 agent 角色标签(SOP 池维护用)

Test Email/api/platform-agents/test-emailPOST1 个接口

POST/api/platform-agents/test-email

模拟给指定 agent 发一封任务邮件,跑完整个处理流程(Ops 界面"测试"按钮用)

Platform Email Configs6 个接口

Platform Email Configs/api/platform-email-configsGETPOSTPATCHDELETE6 个接口

DELETE/api/platform-email-configs/{id}

ops(admin 应用):删除平台邮箱配置

GET/api/platform-email-configs

ops(admin 应用):平台客服邮箱配置列表(仅 owner_scope='platform' 行,不返回密码;平台员工 + support.view)

GET/api/platform-email-configs/{id}

ops(admin 应用):平台客服邮箱配置详情(不返回密码;平台员工 + support.view)

PATCH/api/platform-email-configs/{id}

ops(admin 应用):修改平台邮箱配置(含启停 is_active;传 imap_password 则重新加密)

POST/api/platform-email-configs

ops(admin 应用):新建平台邮箱配置(密码 AES 加密存储;平台员工 + support.view)

POST/api/platform-email-configs/{id}/test

ops(admin 应用):测试 IMAP 连接(dry-run:连邮箱、读 INBOX 状态与最新未读主题,不建单、不改邮件状态;失败 detail 带原始报错原文)

Platform Email Org Mappings4 个接口

Platform Email Org Mappings/api/platform-email-org-mappingsGETPOSTPATCHDELETE4 个接口

DELETE/api/platform-email-org-mappings/{id}

DELETE /api/platform-email-org-mappings/{id} — 删除邮箱域名→组织映射行(校验与列表端点同口径);staff+support.view

GET/api/platform-email-org-mappings

GET /api/platform-email-org-mappings — 平台「邮箱域名→组织」映射列表(带组织名)+组织列表(供页面选择器);staff 会话+support.view(映射只是来信归属线索、非身份证明)

PATCH/api/platform-email-org-mappings/{id}

PATCH /api/platform-email-org-mappings/{id} — 改归属组织/域名/来源/备注、标记验明(verified=true)、停用/启用(is_active);停用只不再命中新来信,历史工单身份证据不回改;staff+support.view

POST/api/platform-email-org-mappings

POST /api/platform-email-org-mappings — 新建邮箱域名→组织映射:域名全局唯一(冲突回已归属组织名供判断共用域名情形),公共邮箱域名(gmail/qq/163 等)永不登记;staff+support.view

Platform Requests2 个接口

Platform Requests/api/platform-requestsGETPATCH2 个接口

GET/api/platform-requests

ops(admin 应用):平台申请列表(平台员工 + crm.view;status=new\

PATCH/api/platform-requests

ops(admin 应用):平台申请状态流转(平台员工 + crm.edit;new→contacted\

Platform Templates31 个接口

Platform Templates/api/platform-templatesGETPOSTPATCHDELETE20 个接口

GET/api/platform-templates

查平台内置标签/装箱单模板库(Template Library),支持类型筛选、名称模糊、启用状态筛选,每行附租户使用数。

POST/api/platform-templates

新建平台内置模板(template_type 只能是 ucc_label/packing_list;name+content 必填,重名返回 409)。

DELETE/api/platform-templates/{id}

删除一条平台内置标签模板(租户已引用的 source_template_id 会被置空)

GET/api/platform-templates/{id}

查一条平台内置标签模板的详情(含完整 ZPL 内容)

PATCH/api/platform-templates/{id}

更新平台内置标签模板(content 变化时 version 自动 +1)

POST/api/platform-templates/{id}/publish

把平台内置模板推送给所有活跃租户(已有同名模板的租户跳过不覆盖)

POST/api/platform-templates/{id}/clone

克隆为 draft 新行(新 family;D68 二期 REQ-20261030-01)

POST/api/platform-templates/{id}/new-version

published 行复制出 version+1 的 draft(supersedes 指回)

POST/api/platform-templates/{id}/activate

draft→published 定版(与 publish 补发分离)

POST/api/platform-templates/{id}/retire

published→retired+is_active=false+留痕(只止下发)

POST/api/platform-templates/{id}/emergency-disable

紧急停用(原因必填):平台行标记+租户副本停用+快照留痕

POST/api/platform-templates/{id}/emergency-restore

按最近停用快照精确恢复被停副本

GET/api/platform-templates/{id}/usage

在用租户明细(副本血统聚合)

GET/api/platform-templates/{id}/thumb

渲染预览缩略图(REQ-20261031-18 §9):经 core 内部端点调 @docklify/lib 真管线样例渲染,ZPL 回 PNG base64、HTML 单据版回样例 HTML;渲染失败 502 大白话(template.view)

GET/api/platform-templates

查平台内置标签/装箱单模板库(Template Library),支持类型筛选、名称模糊、启用状态筛选,每行附租户使用数。

POST/api/platform-templates

新建平台内置模板(template_type 只能是 ucc_label/packing_list;name+content 必填,重名返回 409)。

PATCH/api/platform-templates/{id}

更新平台内置标签模板(content 变化时 version 自动 +1)

DELETE/api/platform-templates/{id}

删除一条平台内置标签模板(租户已引用的 source_template_id 会被置空)

POST/api/platform-templates/{id}/publish

把平台内置模板推送给所有活跃租户(已有同名模板的租户跳过不覆盖)

POST/api/platform-templates/{id}/thumb

编辑器实时预览(REQ-20261102-50,同 GET 路由同管线加 POST 法):Body 带 content 直接渲染未保存内容(不读库不落库,新建未存时路径段传 new),不带则同 GET 渲染已存行(template.edit;GET 仍 template.view;content 超 512KB 回 413;无 content 且 id=new 直接 404)

Extract Jobs/api/platform-templates/extract-jobsGETPOST6 个接口

POST/api/platform-templates/extract-jobs

平台 AI 生成任务(multipart;scope=platform、平台自用组织计量、**月度软上限 200**(D93 定版平台口径;租户侧仍 20);REQ-20261102-52 批三起加同组织串行护栏:已有 analyzing/draft_rounds 任务时 409 generation_in_progress)

GET/api/platform-templates/extract-jobs

平台 AI 生成任务列表

GET/api/platform-templates/extract-jobs/{id}

任务详情(含 proposal)

POST/api/platform-templates/extract-jobs/{id}/confirm

确认步:逐元素四结局处置服务端强制,未处置齐 422、真实数据静态化 400 设防,只落 draft

GET/api/platform-templates/extract-jobs/{id}/rounds

**新增(REQ-20261102-52 批三,D93 §3.8)**:轮次链读取——版本链(轮次/feedback/校验计数/保真报告)+当前轮内容+待确认问题清单+AI 轮次用量(template.view)

POST/api/platform-templates/extract-jobs/{id}/rounds

**新增(同上)**:body.action 分发——create(仅 manual_edit 人工轮;第 1 轮由 confirm 的 `mode:'rounds'` 建,confirm 加法入参、默认行为不变)/feedback_structured(结构化答题→确定性修改→新轮,不调 AI 不计费)/feedback_ai(自然语言修订,经 core 内部 template-revise;AI 轮硬顶 10、第 7 轮起响应带提示)/rollback(只改指针)/preview(三模式 placeholder/sample/values;真单组织钉死 Demo 3PL、retailer 双条件复核,渲染不落盘)/candidates(真单候选 ≤6 带特征标注)/save(过保存准入门后落 platform_templates draft+快照+pending 变量请求)/abandon(template.edit)

Variables/api/platform-templates/variablesGET2 个接口

GET/api/platform-templates/variables

变量注册表清单(经 core 内部端点取真注册表,供 AI 确认步下拉);REQ-20261102-52 起可选 ?organization_id=:带了则 core 在服务端合并该组织扩展字段定义,条目带 source 分组标记(system/extension),不带=纯静态目录(原行为)

GET/api/platform-templates/variables

变更(REQ-20261102-50):kind 放宽为租户 kind 全域(ucc/packing_list/pallet_label/dg/pickup_receipt…),供编辑器变量面板按 5 类取目录;注册表无该 kind 条目回空清单

Counts/api/platform-templates/countsGET1 个接口

GET/api/platform-templates/counts

按类模板总数(REQ-20261104-46):口径与列表仅带 template_type 时的 total 严格一致(全部状态、exact 计数),供 ops 模板页页签计数(template.view)

Variable Requests/api/platform-templates/variable-requestsGET1 个接口

GET/api/platform-templates/variable-requests

待新增变量清单(AI 确认步 pending 处置攒下)

Validate/api/platform-templates/validatePOST1 个接口

POST/api/platform-templates/validate

编辑器实时校验代理(REQ-20261102-50,唯一新增端点):透传 core 内部 template-validate,零规则零落库,返回 unknown_variables/unknown_details(key+服务端近似建议)/advisories/unknown_images/image_message;校验服务不可用 503 fail-closed(template.edit;content 超 512KB 回 413,独立 review P2-3 收紧)

Portal15 个接口

Service Quotes/api/portal/service-quotesGETPOST15 个接口

GET/api/portal/service-quotes/quotes

客户报价列表(Portal;D138 批二):登录态+本组织成员;草稿不可见(过滤),状态附人话映射

GET/api/portal/service-quotes/quotes/{id}

客户报价详情(Portal;批二):CustomerQuoteDetail 白名单 DTO(结构上不含内部备注)+当前版全文/总额人话+授权文案全文(版本→全文事实源取回)+各版差异人话行+can_approve(账单角色且 open)

POST/api/portal/service-quotes/quotes/{id}/approve

客户点击批准(Portal;批二):登录态+本组织账单角色(owner/admin 二次校验)。body `{version_id*, content_hash*}`——哈希绑定复核(不符 409 CONTENT_HASH_MISMATCH、过期 410 QUOTE_EXPIRED);批准留痕含分期扣款授权(P-2)+在档付款方式引用/mandate 状态;总额 ≥$10,000 且未登记 contract_ref → 422 QUOTE_REQUIRES_OFFLINE_CONTRACT 人话分流(P-1);批准成单后 on_approval 里程碑立即转正式+首扣(失败不回滚批准、结果随响应回传);重复批准幂等回放

POST/api/portal/service-quotes/quotes/{id}/reject

客户拒绝报价(Portal;批二):账单角色;body `{reason*}`,拒绝即终态、理由留痕

GET/api/portal/service-quotes/quotes/{id}/messages

议价留言列表(Portal;批二):本组织对客留言(内部备注永不在本面)

POST/api/portal/service-quotes/quotes/{id}/messages

客户留言(Portal;批二):body `{body*, version_id?}`;author_side 服务端强制落 customer、客户端传值忽略

GET/api/portal/service-quotes/orders

客户服务订单+里程碑(Portal;批二):本组织订单全表,每期金额/触发/付款维/交付维附人话映射(只读;验收动作归批三)

GET/api/portal/service-quotes/invoices

客户服务发票(Portal;批二):只列已转正式(草稿不列),状态人话+已付/待付金额(分配 Σ 派生)

GET/api/portal/service-quotes/payments

客户付款记录(Portal;批二):卡扣摘要/线下方式摘要白名单+人话状态(不透传通道原始错误码);证据文件引用仅账单角色可见(P3-3 API 层二次校验),普通成员只见摘要

POST/api/portal/service-quotes/milestones/{id}/accept

客户验收确认(Portal;批三):登录态+本组织账单角色;落 accepted+source='customer';on_acceptance 里程碑随即触发扣款(通道未配置时验收仍落痕、响应带 charge_note=PAYMENT_NOT_CONFIGURED);争议窗内(自动确认后 3 天)也接受确认;重入回放

POST/api/portal/service-quotes/milestones/{id}/dispute

客户提出异议(Portal;批三):组织成员;body `{note*}` 必填,交付维→disputed;自动确认后 3 天争议窗内可提;异议同步一条对客留言给 ops 面;重新交付后可再验收

GET/api/portal/service-quotes/orders/{id}/amendments

客户变更单列表(Portal;批三):草稿不可见,仅 sent/confirmed/rejected;回行附计划快照+内容哈希+人话状态

POST/api/portal/service-quotes/orders/{id}/amendments/{aid}/confirm

客户确认变更单(Portal;批三):账单角色;body `{content_hash*}` 哈希绑定(不符 409 CONTENT_HASH_MISMATCH);确认留痕 platform_quote_approvals(subject_type='amendment')+生效按快照更新未触发 pending 期次(金额/触发/增删),已 invoiced/paid 期次不动;重复确认回放

POST/api/portal/service-quotes/orders/{id}/amendments/{aid}/reject

客户拒绝变更单(Portal;批三):账单角色;sent→rejected 终态,原计划不受影响

GET/api/portal/service-quotes/pdf

客户面 PDF(Portal;批三):`?kind=quote&quote_id=&version_id=` 或 `?kind=invoice&invoice_id=`;仅本组织、草稿 quote 与草稿 invoice 不可见(他组织统一 404 防探测);发票 PDF 含明细行(服务行 qty/unit/amount+税行)

Portal Bridge14 个接口

Users/api/portal-bridge/usersGETPOSTPATCH4 个接口

GET/api/portal-bridge/users

Merchant Portal 服务端经桥接通道查询本商户的用户列表(含角色/来源/启用状态);Header 须带 Bearer PORTAL_BRIDGE_TOKEN

POST/api/portal-bridge/users

Merchant Portal 服务端经桥接通道新建/关联用户:邮箱已存在只做商户关联(不碰密码),不存在则建用户+组织成员+Merchant 角色并关联;Header 须带 Bearer PORTAL_BRIDGE_TOKEN

PATCH/api/portal-bridge/users/{id}

Merchant Portal 经桥接更新本商户下某用户的角色(admin/operator)、启用状态和显示名;Header 须带 Bearer PORTAL_BRIDGE_TOKEN

POST/api/portal-bridge/users/{id}/reset-password

Merchant Portal 经桥重置本商户下某用户的登录密码(至少 8 位);Header 须带 Bearer PORTAL_BRIDGE_TOKEN

预约/api/portal-bridge/appointmentsGETPOST2 个接口

GET/api/portal-bridge/appointments

Merchant Portal 桥接 — 月台预约(REQ-20261025-19 P1)。action=meta(仓库/carrier 名录/本人 receipt+load)/ slots(时段余量)/ list(我的预约,含确认子状态)/ detail;作用域 organization_id + client_id(shared_clients 归属校验),序列化白名单字段

POST/api/portal-bridge/appointments

Merchant Portal 桥接 — 月台预约动作:action=submit(申请即占额,满额回 APPT_SLOT_FULL 大白话)/ client-accept(接受替代时段)/ client-resubmit(改提新时段)/ cancel;状态流转与桌面端共用 lib/appointment-actions.ts

Carrier Appointments/api/portal-bridge/carrier-appointmentsGETPOST2 个接口

GET/api/portal-bridge/carrier-appointments

Carrier Portal 桥接 — 月台预约收件箱(REQ-20261025-19 P2)。Bearer 桥令牌恒时比对 + organization_id + carrier_id 双键作用域(carrier 须属该组织);action=inbox(本 carrier 的 CONFIRMED 起预约,分组 needs_assignment/assigned/accepted/done/cancelled,附名录司机)/ detail(本单详情+指派历史)/ drivers(本 carrier 名下 shared_drivers);序列化显式白名单,承运商成本类字段永不进响应

POST/api/portal-bridge/carrier-appointments

Carrier Portal 桥接 — 派车动作(REQ-20261025-19 P2):action=assign(driver_id 选名录司机或 driver_name+driver_phone 现填;已有 active 指派自动改派,旧行 superseded+旧令牌吊销)/ add-driver(给本 carrier 新增司机,姓名必填);状态流转收口 lib/appointment-assignments.ts

Labelflow/api/portal-bridge/labelflowGETPOST2 个接口

GET/api/portal-bridge/labelflow

Merchant Portal 经桥接通道查询 Label Flow 数据(钱包/租户承运商/运单列表/运单详情/导入模板),Header 须带 Bearer PORTAL_BRIDGE_TOKEN

POST/api/portal-bridge/labelflow

Merchant Portal 经桥接通道执行 Label Flow 全链路操作(报价/打单/建运单/运单报价/打印/批量导入),Header 须带 Bearer PORTAL_BRIDGE_TOKEN

Oms Orders/api/portal-bridge/oms-ordersPOSTPATCH2 个接口

PATCH/api/portal-bridge/oms-orders

取消经桥接刚建的草稿订单(Portal 建 WMS 出库单失败时的回滚用);仅 draft 状态允许取消,并写审计;Header 须带 Bearer PORTAL_BRIDGE_TOKEN

POST/api/portal-bridge/oms-orders

Merchant Portal 服务端经桥接通道代建 OMS 销售订单(与桌面端同一建单链路),客户按商户维度复用/自动创建;Header 须带 Bearer PORTAL_BRIDGE_TOKEN

Ai Usage/api/portal-bridge/ai-usagePOST1 个接口

POST/api/portal-bridge/ai-usage

Portal AI 助理用量代记(REQ-20261026-11):双 Portal 无 service_role key,经桥令牌鉴权由 saas 代记 platform_ai_usage_logs(服务端算 cost,product 由桥声明为 docklify、layer=assistant);body {organization_id, model, input_tokens, output_tokens, status},校验组织存在。

Drayage Documents/api/portal-bridge/drayage-documentsPOST1 个接口

POST/api/portal-bridge/drayage-documents

Merchant Portal 桥接 — Drayage 单证签名(REQ-20261026-27 / D46)。Bearer 桥令牌恒时比对;action=sign{organization_id, client_id, order_id, kind: order\

Products4 个接口

产品/api/productsGETPOSTPATCHDELETE4 个接口

GET/api/products/{id}/images

列出某产品图片库的全部图片,主图优先、同组按创建时间排序

POST/api/products/{id}/images

把一个已上传的统一文档(documents 行)关联进产品图片库,幂等,第一张自动设为主图

DELETE/api/products/{id}/images/{imageId}

删除一张产品图片(删 DB 行 + Storage 文件尽力删),删的是主图时把最早的一张提为新主图

PATCH/api/products/{id}/images/{imageId}

把一张产品图片设为主图(只支持 is_primary: true,并发冲突返回 409 前端重试)

Promo5 个接口

Campaigns/api/promo/campaignsGETPOSTPATCH5 个接口

GET/api/promo/campaigns

活动列表(query: status/limit/offset 分页封顶 100);逐活动带 item_counts(逐行状态计数)

POST/api/promo/campaigns

建活动:body {name, pricing_mode: fixed_price\

GET/api/promo/campaigns/{id}

活动详情+逐行结果(基数快照/活动价/状态/错误码/推价与恢复时间/external_ref 含 simulated 与冲突占用方名)+范围产品与店铺标签

PATCH/api/promo/campaigns/{id}

编辑活动(仅 draft/scheduled;激活后范围与定价冻结,改回 409 PROMO_NOT_EDITABLE);字段同建活动,合并后整体复验

POST/api/promo/campaigns/{id}/actions

动作分发:body {action: stop\

Public10 个接口

Portal/api/public/portalGETPOST5 个接口

GET/api/public/portal/history

客户工单门户的历史工单列表,按邮箱查(公开,不鉴权)

GET/api/public/portal/lookup

客户工单门户按工单号+邮箱查工单摘要(公开,不鉴权)

GET/api/public/portal/ticket/{id}

客户工单门户的工单详情,凭邮箱验证,只展示公开评论(非内部)时间线

POST/api/public/portal/ticket/{id}/comments

客户在工单门户追加评论(公开,不鉴权),邮箱须与工单匹配,已关闭工单不能评论

POST/api/public/portal/ticket/{id}/nudge

客户催单(公开,不鉴权),写一条 [NUDGE] 评论并把优先级升一档,每小时最多催一次

Csat/api/public/csatGETPOST2 个接口

GET/api/public/csat/{token}

公开 CSAT 满意度调查页信息,不鉴权凭 token(返回工单号/标题/是否过期/是否已评)

POST/api/public/csat/{token}/submit

公开提交 CSAT 评分(1-5 星 + 可选留言),每个 token 只能评一次

Package Tiers/api/public/package-tiersGET1 个接口

GET/api/public/package-tiers

公开读取已启用的套餐档位(短信/存储/AI Token),注册流程和租户升级页用

Provision Tenant/api/public/provision-tenantPOST1 个接口

POST/api/public/provision-tenant

官网注册表单验码(公开):按码查 promo_codes 做有效性/有效期/次数校验并回折扣形态,不记账(记账在 provision-tenant)。品牌过滤(565 / D22):官网属 Docklify 面,brand_scope='orderball' 的码返回 `{"ok": true, "valid": false, "error": "wrong_platform", "message": "…"}`(英文人话);all/docklify 码正常验。

线索/api/public/leadsPOST1 个接口

POST/api/public/leads

通用站点留资公开提交(REQ-20261108-12;不鉴权、CORS *;body:source*(来源标记,如 sightbell/cubetrue)/full_name*/email*/company/site_type/intent/note/details(品牌专属字段只进扩展位)/website(蜜罐)/test;落 site_leads(migration 925,service role 写、RLS 仅平台员工);honeypot 静默假成功不落行;同 IP 10 分钟 ≥5 次落行 429 RATE_LIMITED;同 source+email 24h 幂等返回既有 id(created=false);失败统一信封 {ok:false,error,message},校验 400/未配置 503,绝不假成功)

Reports10 个接口

Reports/api/reportsGET/POST/DELETEGETPOST6 个接口

GET/api/reports

已发布报表定义列表(统一报表平台 Reports,只回 published 定义;D78 §4.8,REQ-20261031-50)

POST/api/reports

不支持在线新建报表定义的存根端点:恒返回 405,报表定义由平台注册表维护

GET/api/reports/{code}

报表定义详情:参数 schema、列定义、聚合与口径脚注,附本组织可选的仓库/货主选项(页面选择器用,不用手填 UUID)

POST/api/reports/{code}/run

运行报表:小结果同步返回行数据;估算行数超阈值(默认 50000 行或预估 >10s)转异步,返回 run_id 供轮询。每次运行落 report_runs 审计一行

POST/api/reports/{code}/export

导出 CSV:与运行同一条引擎链(同参数、同口径、同范围),直接回文件流;本次导出同样落 report_runs(action=export)一行

GET/POST/DELETE/api/reports/{code}/subscriptions

报表订阅:POST `{cron, recipients[], format?, params}`(recipients 字符串自动归一、params 存 config 列);DELETE `?id=` 置 cancelled(软取消)。详细条目见 Endpoint details 区同名三条

Runs/api/reports/runsGET2 个接口

GET/api/reports/runs/{runId}

查一次报表运行的状态与结果(异步运行的轮询端点):status 为 running / done / failed / rejected,done 时带 result(返回前按当前口径把维度值标签化)

GET/api/reports/runs/{runId}/export

下载一次已完成运行的 CSV:用该 run 已存的结果按定义列序生成,不重算、口径与直接导出一致;存量结果本身是截断结果时同样带 X-Report-Truncated 头与 --partial 文件名

Embed Token/api/reports/embed-tokenPOST1 个接口

POST/api/reports/embed-token

签发业务页内嵌用的短时令牌(HMAC,TTL 10 分钟):把当前用户的组织+锁定的仓库/货主范围+单个报表 code 绑进令牌,内嵌组件凭令牌调 run / 查 runs,范围不经参数传递

Refresh/api/reports/refreshPOST1 个接口

POST/api/reports/refresh

报表物化刷新(cron 专用):逐组织刷新昨日+今日(UTC 日界,与物化函数口径一致)的报表物化数据;单组织失败不中断其余组织,失败清单在响应里明示

Retailer Logos1 个接口

Retailer Logos/api/retailer-logosGET1 个接口

GET/api/retailer-logos/{code}

GET /api/retailer-logos/{code} — retailer 真 Logo 出图(ops 模板列表用):注册表直链→302 / 模板内嵌图→字节直出 / 两处皆无→404;template.view(与平台模板列表同点)

Retell1 个接口

Webhook/api/retell/webhookPOST1 个接口

POST/api/retell/webhook

POST /api/retell/webhook — Retell 电话客服事件接收端(REQ-20261024-53 / OB-AI-09,设计 retell-voice-agent-design §2.1/§11):验签头 x-retell-signature(v=<ms>,d=<hex>,HMAC-SHA256(rawBody+v, RETELL_API_KEY),5 分钟窗),无登录会话。只处理 call_ended / call_analyzed,其余事件回 200 忽略;call_id 幂等落库:建/更新 tkt_tickets(source=retell_voice、channel=phone、category=system、subject 带 [电话客服] 前缀与来电尾号)+ tkt_retell_calls 通话元数据(方向/尾号/时长/成本/录音/转写/分析字段/知识版本,migration 556);call_analyzed 回填摘要与结论(handoff 升优先级、通话内解决置 resolved);未配 RETELL_API_KEY 回 500 RETELL_NOT_CONFIGURED(fail closed)、验签失败 401、落库失败 500(Retell 最多重试 3 次、超时 10 秒,handler 幂等可重投)

Rules8 个接口

Rules/api/rulesGETPOSTPUT8 个接口

GET/api/rules/{domain}

某 domain 的规则列表,规则定义与当前租户配置合并(无配置用默认值)

PUT/api/rules/{domain}/{ruleId}

更新单条规则的租户配置(开关/权重/参数),upsert tenant_rule_configs

GET/api/rules/{domain}/shipper/{clientId}

某货主的规则三层合并视图(货主配置 > 租户配置 > 系统默认,每条带 source 来源)

PUT/api/rules/{domain}/shipper/{clientId}/{ruleId}

更新某货主的单条规则配置,只写该货主的 shipper_rule_configs,与互斥规则冲突返回 409

GET/api/rules/{domain}/shippers

本租户已启用的货主(client)下拉列表,供规则页的货主选择器取数

GET/api/rules/{domain}/templates

某 domain 的规则预设模板列表

POST/api/rules/{domain}/templates

套用规则预设模板,批量 upsert 租户规则配置,返回生效/跳过条数

POST/api/rules/{domain}/test

规则试算模式,用给定配置模拟跑一次看效果(不写库,不产生真实业务动作)

Settings9 个接口

My Ai/api/settings/my-aiGETPOST5 个接口

GET/api/settings/my-ai

店主面状态:agent 身份/状态/凭证(尾 4 位+到期)/生效三档/岗位工具清单/待提计数。鉴权:店主会话+组织归属(brand=orderball)。

POST/api/settings/my-ai

店主面写操作(body.action 分发:create_agent/update_config/confirm/suspend/resume/revoke/retire 共 7 个逻辑端点):写操作过 own_ai_agent 功能门(Free 回 PRO_REQUIRED 引升档)。

POST/api/settings/my-ai/pairing

签发一次性配对码并渲染入职提示词(码只随提示词出门,响应不另带明文字段)。

GET/api/settings/my-ai/activity

活动时间线(工具审计+提议状态合并分页)+待决提议列表。

POST/api/settings/my-ai/activity

提议决策(approve/reject;批准走原子抢占执行、失败留痕可再批、72h 过期物化为 rejected 不执行)。

Tenant/api/settings/tenantGETPUT2 个接口

GET/api/settings/tenant

读取当前组织的租户区域设置,无行则返回默认值(不落库)

PUT/api/settings/tenant

更新租户区域设置,仅 Owner/Admin 可改(industry_profile 有白名单校验)

Dock Affinity/api/settings/dock-affinityGETPUT2 个接口

GET/api/settings/dock-affinity

月台亲和配置矩阵(D125 §4.2):?warehouse_id=*&yard_id= → 候选月台池+各区优先序+未配区+孤儿亲和标记(区已不存在的亲和行单列)。门面批同端点扩展字段(不加新端点):candidate_docks 带 6 个能力字段(supports_reefer/supports_hazmat/equipment_types/has_leveler/has_restraint/use_for);`audit`=dock_affinity_audit 最近 50 条(before/after 已解析为月台 code 序);`window_settings`={dock_reserve_window_min, dock_default_window_min}(无设施行回落默认 60/120);`unrecorded_docks`=能力 6 字段全默认的月台清单(§14 未补录呈现);`orphan_affinities`=区已不存在的 active 亲和行

PUT/api/settings/dock-affinity

亲和保存三分支(同端点按 body 分流,互不影响):①按区替换 {warehouse_id*, area_kind*, area_code*, docks*:[{dock_location_id, priority}]}——整批校验(priority 连续、月台在候选池且未 disabled、区现存)不过整批拒绝;通过后调 881 事务型 RPC dock_affinity_replace 单事务替换该区 active 序并写 dock_affinity_audit 前后快照;docks 空数组=清空该区。②窗口设置:body 带 `window_settings` {dock_reserve_window_min, dock_default_window_min} 时只保存两窗口(upsert 设施设置行),不走按区替换。③孤儿停用(门面窄修):body 带 `deactivate_affinity_ids`(亲和行 id 数组,≤100)时只停用指定行(is_active=false,逐行校验仓库归属/存在性、幂等)并按区分组写 dock_affinity_audit(action='disable',before/after 为该区 active 序快照);顺序两写非事务 RPC(整区替换语义不合单行停用、新 RPC 需新迁移,取舍见设计稿实现落地追记),审计写失败时响应文案明示「已生效但写记录失败」

Shared3 个接口

库位/api/shared/locationsGETPOSTPATCH3 个接口

GET/api/shared/locations

WMS/YMS 共享位置查询(装卸 dock / 停车 spot / 等候 waiting),支持按类型/堆场/仓库/区域筛选

POST/api/shared/locations

新建一个 WMS/YMS 共享位置(dock/spot/waiting)

PATCH/api/shared/locations

更新月台能力字段(REQ-20261106-20 门面批,D125 §4.3/§11:能力不新增端点、走既有 shared 读写路径加字段):body {id*, supports_reefer?, supports_hazmat?, equipment_types?, has_leveler?, has_restraint?, use_for?}——仅 location_type='dock' 行可写;布尔四项逐项校验、equipment_types 须字符串数组(去重去空、上限 30)、use_for 限 any/inbound/outbound,非法回 400;写穿 shared_locations 本行(YMS 车位图弹窗与 Master Data 库位两维护面共用此唯一写路径,两面回显同一值)

Sign2 个接口

Sign/api/signGETPOST2 个接口

GET/api/sign/{token}

公开电子签署页数据,无需登录,token 即凭证(首次打开记查看事件)

POST/api/sign/{token}

提交电子签名(PNG 签名图 + 落笔坐标),全部签署人签完后请求变为 completed

Sms7 个接口

Packages/api/sms/packagesGETPOSTPATCHDELETE4 个接口

GET/api/sms/packages

列出全部短信充值档位(含停用),按 sort_order 排序;平台员工鉴权(billing.view 权限)。

POST/api/sms/packages

新建短信充值档位(名称、条数、价格必填);平台员工鉴权(billing.view 权限)。

DELETE/api/sms/packages/{id}

停用单个短信档位(软删:is_active 置 false,不物理删除);平台员工鉴权(billing.view 权限)。

PATCH/api/sms/packages/{id}

修改单个短信档位(名称/条数/价格/排序/启停,按需传字段);平台员工鉴权(billing.view 权限)。

Inbound/api/sms/inboundPOST1 个接口

POST/api/sms/inbound

Twilio 短信 webhook(公开端点),处理用户回复的 STOP 退订 / START 重新订阅,验签后回 TwiML

Send/api/sms/sendPOST1 个接口

POST/api/sms/send

手动发送消息,channel 可选 app 内通知(默认)或 sms 短信(余额不足时降级 app)

Usage/api/sms/usageGET1 个接口

GET/api/sms/usage

平台短信余量/消耗总览(各组织余额、开关状态、近 30 天发送条数与消耗);平台员工鉴权(billing.view 权限)。

Sourcing26 个接口

Listings/api/sourcing/listingsGETPOSTPATCH6 个接口

GET/api/sourcing/listings

选品池列表(暂存目录;query: connection_id/status/category/q/limit/offset 分页、pending_only=1 只看待确认成本、has_change=1 只看有变更摘要;响应带 categories 类目清单;逐 variant 现算 sale_price/margin_pct(按组织定价规则);530 落库后带 last_change 变更摘要与 title_override,列未落库自动降级不报错;status=published 时逐行带 push_state/source_count/primary_source)。**REQ-20261031-21(D76)加法扩展**:新增可选 query `client_id`(按商家(merchant)等值筛选选品归属,不传时行为与此前逐字一致,类目选项查询同步叠加该筛选);逐行返回列补 `client_id` 与 `merchant_name`(按行 client_id 回填商家名,与 Integration connections 列表同口径;无归属行两值为空/merchant_name=null)——Docklify Integration 选品池页的商家筛选与归属列即经此参数与返回列实现

POST/api/sourcing/listings/pull

立即拉取一个货源连接的产品目录到选品池(无凭证走模拟样例目录,响应带 simulated 标注;更新行落 last_change 变更摘要)。拉取范围按连接 config 圈定(CJ:pull_keywords 词组逐词拉取、本轮按平台产品合并去重,响应新增 duplicates 计数;单值 pull_keyword 存量兼容;pull_category_id 叠加 → listV2 keyWord/categoryId 服务端过滤);body 可选 max_items/max_pages 设本轮硬顶(缺省执行层保守默认 1000/100),到顶停拉且响应带 truncated=true 与已拉计数,截断轮次不做下架判定(delisted_skipped)。主拉后自动补拉既有降级行(详情失败落的无变体行)详情回填变体:预算与本轮硬顶共用(max_items − 已拉数),响应新增 backfilled/backfill_attempted/backfill_failed 计数(2026-10-29 两缺陷修复,待发版)。**REQ-20261031-21(D76)空绑拒绝**:连接未绑定商家(client_id 为空)时拉品直接拒绝、回 `CLIENT_UNBOUND`(人话:这条连接还没绑定商家,先在连接编辑页补绑商家再拉品),连接器零调用;拉入行的归属一律取连接当前绑定的商家,调用方不传、也不能指定 client_id。**REQ-20261031-74 加法扩**:body 可选 `keyword`——本轮拉取关键词覆盖(单轮生效、绝不回写连接 config.pull_keywords),供 AI 助理 sourcing_pull 按客人邮件关键词拉品复用同一端点

POST/api/sourcing/listings/publish

发布门:勾选的暂存产品过合规/资料检查后建 OMS 产品 + 写供给 mapping(按 item 判重幂等);body 带 dry_run=true 时只做预检逐条返回 checks(ready/blocked/already_published/skipped),不写库。**REQ-20261031-21(D76)归属守卫**:逐行结果新增两个 blocked 原因码(dry_run 预检与正式发布共用同一检查段)——`CLIENT_MISMATCH`(选品的归属商家与所属连接当前绑定的商家不一致,人话提示先在选品池里核对归属)、`CLIENT_UNBOUND`(选品尚无归属商家,或所属连接未绑定商家;先给连接补绑商家再发布);归属一律以选品行自身的 client_id 为准、不信任调用方传入的商家参数,正常路径(未改过连接归属)永不触发

GET/api/sourcing/listings/{id}

单条详情(REQ-20261030-05 新增,活路由在 apps/core):组织内单行+连接名+逐变体售价回算与 `price_overridden` 标记+已建产品 OMS SKU 反查+push_state/published_at(最早 mapping 近似)+服务端派生 `completeness`(七项三档,只回 code/level/facts;raw_payload 与 detailError 原文永不下发;样例行按 fixture 豁免详情项);G-11 起(REQ-20261030-19)另带 `description`(平台原描述·清洗后 HTML,raw 仍不整包下发)+`description_override`/`images_override` 两覆盖原值(677 列容错合并,列未落库自动降级),完整度 images 项按生效图集、新增 description 提醒项

PATCH/api/sourcing/listings/{id}

忽略/恢复、产品级售价覆盖(price_override)、成本冻结确认(confirm_cost 清 pending_cost_price)、保持旧成本(dismiss_cost 清 pending 并在 last_change 留痕)、发布标题覆盖(title_override,null 清除;发布时优先于平台标题);G-11 起(REQ-20261030-19)加描述覆盖(description_override:纯文本,空/null 清除恢复平台原描述,上限 20000 字)与图片覆盖(images_override:URL 数组,首张封面,空数组=清空全部,null 清除恢复平台图集;逐项 http(s) 校验、≤30 张)——发布门与推 Shopify 均按生效值(覆盖优先)执行

POST/api/sourcing/listings/{id}/ai-copy

AI 商品文案生成(G-23,REQ-20261030-19):body {lang: en/zh/es};按产品事实(生效标题/类目/变体规格/已存描述底稿/平台原描述摘要)经平台 AI Router(aiChat,purpose=sourcing_copy)生成 {title, description} 候选;**只生成不落库**,卖家在编辑器采用并保存后才经 PATCH 写覆盖列;失败 502 AI_COPY_FAILED(页面降级手工编辑)

订单/api/sourcing/ordersGETPOSTPUT5 个接口

GET/api/sourcing/orders

代发监控读模型(G-09,REQ-20261030-24,活路由在 apps/core;会话或内部令牌):近 N 天 dropship PO+平台单统一状态+待办五计数(待审核/待付款/待付款超时/回执未知/未解异常)+按连接日汇总(今日提交数额/待付款/实付/对账差)+急停状态;UUID 只在服务端

POST/api/sourcing/orders

代发动作分发:`{action:'evaluate', order_id}` 触发六门评估(内部令牌=auto 触发、会话=manual 触发;manual 档 auto 只回 suggested)/ `{action:'submit', po_id, margin_override_reason?}` 提交(全门控复检:急停/live/测试单/复检/毛利/先查后建;回执未知停置对账不重提)/ `{action:'reconcile', po_id}` 未知回执对账(查到接管、满 30 分钟查不到才放回草稿)/ `{action:'reroute', line_id, target}` 行级改路由 / `{action:'verify', po_id}` 下单前可售复检

POST/api/sourcing/orders/sync

单连接状态同步一轮:`{connection_id}` → 轮询未终态平台单、应用状态事件(只进不退)、落包裹并回写渠道、实付对账调差;回 `{polled, advanced, errors}

GET/api/sourcing/orders/settings

代发组织设置读:急停 sourcing_auto_order_kill、毛利下限、单笔/日累计自动阈值、冷启动单数、待付款提醒/超时小时(oms_routing_settings 键,缺省回定版默认)

PUT/api/sourcing/orders/settings

代发组织设置写:只写 body 传入的键,负数/非法值丢弃,回读为准;关闭急停(kill_switch true→false)须带 kill_switch_reason(非空),缺失回 400 KILL_SWITCH_OFF_REASON_REQUIRED,成功关闭落急停审计行(by/reason/at),开启急停免原因

设置/api/sourcing/settingsGETPOSTPUT3 个接口

GET/api/sourcing/settings

定价规则(组织级三键)+ 各货源连接策略/虚拟仓/熔断状态

PUT/api/sourcing/settings

更新定价规则(markup_pct/fixed_add/margin_pct + round_to)

POST/api/sourcing/settings/preview

定价试算(只算不写):body {cost, pricing:{type,value,round_to}} → {price};售价公式单一事实源 computeSalePrice,门面设置页例算经此端点试算(REQ-20261030-04 返修 P2-1)

Compliance Terms/api/sourcing/compliance-termsGETPOSTDELETE3 个接口

GET/api/sourcing/compliance-terms

合规词库列表(首次访问自动落预置品牌/违禁词)

POST/api/sourcing/compliance-terms

新增合规词(term/term_type/action=block 或 warn)

DELETE/api/sourcing/compliance-terms/{id}

删除一个合规词

Mappings/api/sourcing/mappingsGETPOSTDELETE3 个接口

GET/api/sourcing/mappings

产品映射两视图(view=mapped 已映射分页 / unmapped 未映射 SKU 清单;q 按外部 SKU/标题/产品名 SKU 搜索;未映射口径排除 ignored/delisted 的 listing)

POST/api/sourcing/mappings

手动绑定供货 SKU → 产品(写 shared_product_mappings;同键停用行复活改绑、active 行幂等返回;成功顺手 resolved 同键 open 的 unmapped 异常)

DELETE/api/sourcing/mappings?id=

解绑一条映射(软停用 is_active=false;仅限 sourcing 类别连接的行,越界 404 不泄露存在性)

Exceptions/api/sourcing/exceptionsGETPOST2 个接口

GET/api/sourcing/exceptions

mapping 异常队列(open/resolved/ignored;与 /api/integration/mappings/pending 同一事实源;query: type 按类型筛选;响应带 counts 按类型 open 计数与每行 connection_name;context 含来源产品与候选 candidates[{product_id, sku, name, via, confidence}])

POST/api/sourcing/exceptions

处理一条异常:bind 绑定产品(写 shared_product_mappings 并回填异常行 resolved_mapping_id;重复提交幂等)/ ignore 忽略

库存/api/sourcing/inventoryPOST1 个接口

POST/api/sourcing/inventory/sync

立即同步一个货源连接的平台库存到虚拟仓(策略后量;只写 qty/feed_synced_at)。库存只定向同步选品池既有 listings 的 variant SKU(pullInventory 传 SKU 集,响应带 targeted_skus);选品池为空时返回 skipped+reason=no_listings,不做平台全目录枚举。收集 SKU 前先补拉降级行(无变体/detailError 在案)详情回填变体(单轮上限 50,补到的行当轮即纳入定向集),响应新增 backfilled/backfill_attempted/backfill_failed 计数(2026-10-29 两缺陷修复,待发版)

Overview/api/sourcing/overviewGET1 个接口

GET/api/sourcing/overview

概览聚合(批一新增):待办四计数(成本待确认/异常 open/未映射 SKU/库存过期连接数,未映射口径复用映射页 listUnmappedSkus total)、各货源连接健康(最近拉取/最近库存同步/是否过期/目录数/已发布数/有无凭证)、选品池与产品库规模;子项失败分项降级返回 null 不 500

Keyword Assist/api/sourcing/keyword-assistPOST1 个接口

POST/api/sourcing/keyword-assist

关键词助手(REQ-20261030-19):body {connection_id, intent≤200 字};仅 pull_scope='keyword' 且实现了命中数试探的货源连接可用(否则 400 KEYWORD_ASSIST_NOT_SUPPORTED);平台 AI 通道(aiChat,purpose=sourcing-keyword-assist)产英文候选(清洗后 ≤6 个),逐候选只问命中数不真拉(连接器 probeKeywordCount,CJ=listV2 page=1&size=1;限流即停探、余下 probed=false);LLM 全挂回 200 {llm_available:false, candidates:[]} 降级不报错;响应 {llm_available, simulated, candidates:[{keyword, count

产品/api/sourcing/productsPOST1 个接口

POST/api/sourcing/products/push-shopify

把已发布产品推到 Shopify(渠道 SKU=OMS SKU 并回写 mapping;无凭证返回 simulated 不写 mapping)。定价(REQ-20261030-04):目标连接 config 配了 channel_pricing_rule(与组织规则同形)时,逐产品经发布 mapping 回溯货源 listing 成本、用 priceVariant 按渠道规则现算推送价(优先级:单品 price_override > 渠道规则 > 组织默认;无成本依据回落产品 unit_price);已存在产品再推时解析价与在架价不同才刷 variant 价(规则变更不自动回推);逐条结果新增 price/price_source(product_price/channel_rule/override/product_price_no_cost_basis),simulated 结果同样带将推价格

Support9 个接口

Tickets/api/support/ticketsGETPOST4 个接口

POST/api/support/tickets

提交支持工单(抽屉 Report Issue/Ask Rollie 转单)。鉴权:必须登录(`resolveOmsContext`,无会话 401 `UNAUTHORIZED`,不走匿名通道);组织按会话派生。入参要点:`subject`(必填)、`description`(必填)、`category?`(billing/inbound/outbound/inventory/system/other)、`brand?`(docklify/orderball/yardor,非法值落 docklify)、`client_request_id?`(幂等键,重复提交命中回原单 `{ticket_id, ticket_no, duplicated:true}` 不新建)、`screenshot? {data_url, annotation}`(图片 ≤10MB,解码失败按无图降级不挡单;annotation 为 §11 定版空格式预留)、`attachment_ids?`(预上传附件 id,上限 5,仅认领本人未挂单附件)、`context_env?`(现场包 drawer profile,服务端白名单重组+脱敏后落 `assist_context_packs`)、`assist_chat_session_id?`、`escalated?`(红线转单时置 `escalated_at` 并附内部评论)。落单口径:`owner_scope='platform'`、`organization_id=null`、`source='app_drawer'`、`channel='in_app'`、`priority='medium'`、`status='open'`、`identity_level='L3'`;建单后 best-effort 触发 Support 绑定分派+`ticket.assigned` 桥事件(失败只留痕、不阻断回号)。错误要点:400 标题/描述缺失等入参错误(人话 detail);500 `SUPPORT_INTERNAL`(含 858 未应用时缺列失败,不假报成功)。

GET/api/support/tickets

My Support Tickets 列表。鉴权:必须登录。入参:query `page`(默认 1)、`page_size`(默认 20、上限 50)。隔离:`created_by`=本人+`owner_scope='platform'`,按 `updated_at` 倒序、服务端分页(`count: exact`);每行附 `last_public_reply_at`、`has_unread` 与用户侧状态键 `user_status`(open→received/in_progress→in_progress/pending→awaiting_you/resolved·closed→resolved)。错误要点:401 未登录。

GET/api/support/tickets/{id}

我的支持工单详情+公开时间线。鉴权:必须登录。隔离:`created_by`=本人+`owner_scope='platform'` 才可读,否则 404 `SUPPORT_TICKET_NOT_FOUND`(不泄露存在性);返回工单+公开时间线(作者显示名、本人/管理员标记)+附件列表,内部备注永不返回。2026-11-05(REQ-20261105-19)加 `context` 段:提交时现场包(assist_context_packs 按 ticket_id 取最新一行)的白名单映射(app/route/页面标题/仓库/组织/提交人/设备/网络/错误日志/面包屑等)+截图签名 URL(r2PresignedDownload,3600 秒);无包回 `context: null`,降级包带 `capture_degraded` 标记,查包/签名失败降级不影响详情本体。

POST/api/support/tickets/{id}/actions

我的支持工单动作(单端点三分发)。鉴权:必须登录且为本人单(隔离同详情)。入参:`{action, body?}`——`reply`(追加公开评论)、`confirm`(仅 resolved→closed,记本人确认留痕)、`reopen`(resolved/closed→open;closed 超 30 天回 400 `REOPEN_WINDOW_EXPIRED` 人话文案;`body` 给了另加公开评论)、`attach`(详情补图:`attachment_ids` 为预上传附件 id,只认本人上传且未挂单者,单内附件总量上限 5,超限 400 `ATTACHMENT_LIMIT`、不可认领 400 `ATTACHMENT_NOT_CLAIMABLE`)。错误要点:400 未知 action;404 非本人/非 platform 单;409 `INVALID_TICKET_TRANSITION` 非法状态迁移。

Admin/api/support/adminGETPOST3 个接口

GET/api/support/admin/tickets

Admin Support Tickets 列表+统计(同端点 `?mode=stats` 出聚合)。鉴权:必须登录且为本组织管理员(`resolveAdminContext`+`isOrgAdmin`,非管理员 403 `FORBIDDEN_NOT_ADMIN`)。隔离:`submitter_org_id`=本组织+`owner_scope='platform'`。列表入参:`page`/`page_size`(默认 20、上限 50)、`created_by?`、`status?`(内部五态或用户侧四键均可,服务端映射展开);每行附 `submitter_name`。`?mode=stats` 回三指标:`submitted_this_month`(本月提单数)、`avg_first_response_hours`(本月已响应单首次响应均值,服务端聚合、上限 1,000 行有界)、`open_count`(未结数)。错误要点:401 未登录;403 非管理员。

GET/api/support/admin/tickets/{id}

Admin 单详情+公开时间线(实现修订补齐,设计稿 §16.1 端点 8;§4.8 要求 Admin 可看每单公开时间线)。2026-11-05(REQ-20261105-19)同样附 `context` 段(口径同用户侧详情)。鉴权:本组织管理员(同上,403 `FORBIDDEN_NOT_ADMIN`)。隔离:`submitter_org_id`=本组织+`owner_scope='platform'` 才可读,否则 404 `SUPPORT_TICKET_NOT_FOUND`;返回工单+`submitter_name`+公开时间线+附件列表,内部备注永不下发。

POST/api/support/admin/tickets/{id}/actions

管理员动作(单端点三分发)。鉴权:本组织管理员且单属本组织提交(隔离同 Admin 详情)。入参:`{action, body?}`——`reply`(以管理员身份补充公开评论,时间线带管理员标记)、`confirm`(代确认:仅 resolved→closed,内部留痕记明代确认人+管理员角色)、`reopen`(代重开,口径同用户侧、含 30 天窗口)、`attach`(代为补充附件,认领口径同用户侧:只认管理员本人上传且未挂单者,总量上限 5)。权限边界:**不提供**关未解决单/改派/改优先级等平台处理动作,未知 action 回 400。错误要点:400 未知 action;404 非本组织单;409 非法迁移;403 非管理员。

Attachments/api/support/attachmentsGETPOST2 个接口

POST/api/support/attachments

附件预上传(图片先落 R2 拿引用,提交只带引用)。鉴权:必须登录。入参:`data_url`(图片 data URL,仅图片 MIME、≤10MB)、`file_name?`。落 `tkt_attachments`(`ticket_id=null`、`uploaded_by`=本人、`file_url`=R2 键、`scan_status='unscanned'`),回 `{id}`。错误要点:400 图片不合法/超限(人话 detail);401 未登录。

GET/api/support/attachments/{id}/download

支持工单附件下载(实现修订补齐,设计稿 §16.1 端点 9;`file_url` 为 R2 键需签名下载,照 `/api/tickets/attachments/{id}/download` 先例)。鉴权:必须登录。三路授权任一成立:①未挂单附件且 `uploaded_by`=本人;②已挂单且工单 `created_by`=本人;③组织管理员且工单 `submitter_org_id`=本组织(工单一律在 `owner_scope='platform'` 内查)。下发:R2 键经 presigned URL(1 小时)302 跳转,`http(s)` 直链直接跳转。错误要点:404 不可见(不泄露存在性);403 `QUARANTINED` 隔离件(`scan_status='quarantined'`)在签发前拦截。

Tickets64 个接口

Tickets/api/tickets/ticketsGETPOSTPATCHDELETE17 个接口

GET/api/tickets/tickets

工单列表,支持多条件筛选和关键词搜索

POST/api/tickets/tickets

新建工单:工单号自动取,SLA 时限按优先级自动算,没指定客服时按租户策略自动分配

DELETE/api/tickets/tickets/{id}

删除工单(评论和附件级联删除)

GET/api/tickets/tickets/{id}

工单详情,含评论和附件

PATCH/api/tickets/tickets/{id}

更新工单:状态流转走状态机校验,resolved 自动写 resolved_at,状态变更会通知客户

POST/api/tickets/tickets/{id}/assign

指派工单:给人工客服(`assignee_id`)或给 AI Agent(`assignee_agent_id`,REQ-20261025-09 包1「分派即打号」),二选一;open 状态的工单会自动转成处理中

POST/api/tickets/tickets/{id}/handback

回交 Agent(REQ-20261025-09 包1):人工处理完一段后,把已分派给 AI Agent 的工单连同补充说明交回该 agent 继续处理——同一张单、全部历史都在,不新开单

POST/api/tickets/tickets/{id}/close

关闭工单:状态变已关闭,通知客户并自动发 CSAT 满意度调查

GET/api/tickets/tickets/{id}/comments

工单评论列表,按创建时间正序(含作者姓名)

POST/api/tickets/tickets/{id}/comments

发表工单评论:公开回复会通知客户并记首次响应时间,内部备注不通知

POST/api/tickets/tickets/{id}/csat/send

手动重发 CSAT 满意度调查(没建过先建,客户已评过的不再重发)

GET/api/tickets/tickets/{id}/docs

工单关联的业务单据列表(含前端可跳转路径)

POST/api/tickets/tickets/{id}/merge

把重复工单合并到目标工单:评论/附件/关联单据/邮件全部并过去,本单关闭并指向目标单

POST/api/tickets/tickets/{id}/resolve

解决工单:状态变已解决,通知客户并自动发 CSAT 满意度调查

POST/api/tickets/tickets/batch-assign

批量指派工单给客服(assignee_id 传 null 为取消指派)

POST/api/tickets/tickets/{id}/transfer-scope

POST /api/tickets/tickets/[id]/transfer-scope — 租户工单转平台支持(owner_scope/brand 切换、双指派清空、落 transfer_out 事件+交接内部备注;REQ-20261107-52)

POST/api/tickets/tickets/batch-cancel

批量取消工单:只有 open/pending/处理中的可取消,已解决/关闭的跳过并返回原因

Email Configs/api/tickets/email-configsGETPOSTPATCHDELETE6 个接口

GET/api/tickets/email-configs

邮箱监控配置列表(不返回密码)

POST/api/tickets/email-configs

新建邮箱监控配置,密码 AES 加密存储;首次创建会自动插默认 AI 规则

DELETE/api/tickets/email-configs/{id}

删除一个邮箱监控配置

GET/api/tickets/email-configs/{id}

邮箱监控配置详情(不返回密码)

PATCH/api/tickets/email-configs/{id}

修改邮箱监控配置,只传要改的字段;传 imap_password 会重新加密存储

POST/api/tickets/email-configs/{id}/test

测试邮箱 IMAP 连接:只取 1 封未读邮件的主题验证,不建单

Ai Rules/api/tickets/ai-rulesGETPOSTPATCHDELETE5 个接口

GET/api/tickets/ai-rules

AI 工单自动处理规则列表,按优先级从高到低排序

POST/api/tickets/ai-rules

新建一条 AI 工单自动处理规则

DELETE/api/tickets/ai-rules/{id}

删除一条 AI 工单自动处理规则

PATCH/api/tickets/ai-rules/{id}

修改一条 AI 工单自动处理规则,只传要改的字段

POST/api/tickets/ai-rules/test

Dry-run 测试:给一段邮件正文/主题,看 AI 分类结果和会命中哪条规则(不建单)

Domain Mappings/api/tickets/domain-mappingsGETPOSTPATCHDELETE5 个接口

GET/api/tickets/domain-mappings

邮箱域名到客户的映射列表(带客户名),用于邮件自动归户

POST/api/tickets/domain-mappings

新建邮箱域名到客户的映射(校验域名格式、唯一性,公共邮箱域名不允许)

DELETE/api/tickets/domain-mappings/{id}

删除一条邮箱域名映射

PATCH/api/tickets/domain-mappings/{id}

修改一条邮箱域名映射,只传要改的字段(域名/客户/备注都走新建同等校验)

POST/api/tickets/domain-mappings/test

Dry-run 测试:输入一个邮箱地址,看多级匹配会归到哪个客户(不建单不写库)

Auto Assign/api/tickets/auto-assignGETPUT4 个接口

GET/api/tickets/auto-assign/config

取本租户工单自动分配配置(策略 + 客服池 + 上次分配到谁)

PUT/api/tickets/auto-assign/config

更新本租户工单自动分配策略(禁用/轮流/按技能)和参与分配的客服名单

GET/api/tickets/auto-assign/skills

本租户客服技能标签列表(供按技能自动分配用)

PUT/api/tickets/auto-assign/skills

批量更新客服技能标签(按 user_id 逐条 upsert)

Webhooks/api/tickets/webhooksGETPOST4 个接口

GET/api/tickets/webhooks/wecom

企业微信渠道说明(T18/D50/REQ-20261026-31):微信客服为拉取式接入(kf/sync_msg),本端点回渠道模式说明

POST/api/tickets/webhooks/wecom

企业微信入站同步触发(T18/D50):头 `x-wecom-sync-secret`(env WECOM_SYNC_SECRET,未配 503),body `{ organization_id }`;按 tkt_channel_configs 的企微配置(迁移 615)增量拉取微信客服消息 → 先占位认领去重 → 绑定解析 → 建单/追加(tkt_tickets channel='wecom'、绑定命中落 client_id);未配 WECOM_CORP_SECRET 时为模拟模式(simulated 明示)。作用域只从绑定行派生,涉钱/涉敏按 T17/D48 升级分类落内部备注+回升级确认话术+提醒成员。窄修 P2-4:615 未应用(config degraded)时不硬阻断——CorpID/客服账号以 env(WECOM_CORP_ID/WECOM_OPEN_KFID)兜底跑无绑定降级同步,响应体带 `degraded` 与逐条 stats;成员提醒收件人 env WECOM_STAFF_USERIDS

POST/api/tickets/webhooks/sms

Twilio 短信回调:验签后按接收号码找租户,建单或追加到工单,并回一条确认短信

POST/api/tickets/webhooks/whatsapp

Twilio WhatsApp 回调:验签后按接收号码找租户,建单或追加到工单,并回一条确认消息

Knowledge Base/api/tickets/knowledge-baseGETPOSTPATCHDELETE4 个接口

GET/api/tickets/knowledge-base

工单知识库(FAQ)列表,可按关键词或语言筛选

POST/api/tickets/knowledge-base

新建一条知识库 FAQ

DELETE/api/tickets/knowledge-base/{id}

删除一条知识库 FAQ

PATCH/api/tickets/knowledge-base/{id}

修改一条知识库 FAQ,只传要改的字段

Macros/api/tickets/macrosGETPOSTPATCHDELETE4 个接口

GET/api/tickets/macros

常用回复宏列表(看得到共享宏和自己创建的个人宏)

POST/api/tickets/macros

新建一条常用回复宏(默认共享)

DELETE/api/tickets/macros/{id}

删除一条常用回复宏,只能删除自己创建的

PATCH/api/tickets/macros/{id}

修改一条常用回复宏,只能修改自己创建的,只传要改的字段

Sla Policies/api/tickets/sla-policiesGETPOSTPATCHDELETE4 个接口

GET/api/tickets/sla-policies

SLA 策略列表(含客户名),client_id 为空的表示租户默认策略

POST/api/tickets/sla-policies

新建(或覆盖)SLA 策略:按客户+优先级定义首次响应和解决时限

DELETE/api/tickets/sla-policies/{id}

删除一条 SLA 策略

PATCH/api/tickets/sla-policies/{id}

修改一条 SLA 策略的时限和升级人,只传要改的字段

Ai Drafts/api/tickets/ai-draftsGETPOST3 个接口

GET/api/tickets/ai-drafts

AI 自动回复待审核草稿列表,可按状态或工单筛选(默认只看待审核)

POST/api/tickets/ai-drafts/{id}/approve

审核通过 AI 回复草稿:按确认(可修改)的主题正文发邮件给客户,并在工单里留公开评论

POST/api/tickets/ai-drafts/{id}/reject

驳回 AI 回复草稿,工单转回人工处理并留一条内部备注记驳回原因

Channels/api/tickets/channelsGETPUT2 个接口

GET/api/tickets/channels/config

取本租户工单渠道配置(WhatsApp/SMS/WebChat 开关和号码)

PUT/api/tickets/channels/config

更新本租户工单渠道配置(开启渠道必须先有对应号码)

Attachments/api/tickets/attachmentsGET1 个接口

GET/api/tickets/attachments/{id}/download

工单附件下载:生成 1 小时有效的下载链接后 302 跳转(不是 JSON 返回)

Csat/api/tickets/csatGET1 个接口

GET/api/tickets/csat/stats

客户满意度(CSAT)统计:平均分、回复率、评分分布和近 30 天趋势,供 dashboard 卡片用

Performance/api/tickets/performanceGET1 个接口

GET/api/tickets/performance

工单绩效报表(REQ-20261107-46 重建):团队汇总(新建量/解决量/解决率/平均首次响应/平均解决时长/CSAT/SLA 达成率与超时数)+按处理人(人+AI Agent 统一)统计+状态/渠道/优先级分布+按日趋势。口径:工单量按 created_at 落窗、解决量按 resolved_at 落窗;SLA 仅统计带 sla_due_at 的新建队列(未结未到期不入达成率分母);tickets 主查询为唯一硬依赖,辅助段失败降级(degraded 列明)

Team Members/api/tickets/team-membersGET1 个接口

GET/api/tickets/team-members

本租户客服团队成员列表(用于 @ 提到候选人)

Assignees/api/tickets/assigneesGET1 个接口

GET/api/tickets/assignees

GET /api/tickets/assignees — 指派候选名单(人+Agent 一次返回:可选性+六语置灰原因+在手未结数;参数 ticket_ids(逗号分隔,≤200)或 category;REQ-20261107-52)

Webchat/api/tickets/webchatPOST1 个接口

POST/api/tickets/webchat

网站聊天小部件消息入口(公开接口):限流后找访客的待处理工单,没有就新建、有就追加

Utilities19 个接口

Load Plans/api/utilities/load-plansGETPOST7 个接口

POST/api/utilities/load-plans

新建集装箱装载方案(草稿),方案编号自动生成 LP-YYYY-NNNN

GET/api/utilities/load-plans/{id}

装载方案详情,一次返回方案基本信息 + 货物清单 + 分柜结果(未计算时分柜为空)

POST/api/utilities/load-plans/{id}/calculate

对方案货物执行 3D 装箱计算(Extreme Point 启发式,4 策略并跑取最优),重量上限恒为硬约束

POST/api/utilities/load-plans/{id}/generate-booking

按分柜结果一键生成 Drayage booking 草稿(1 柜 1 单),柜型/总重/利用率自动带入备注,幂等

POST/api/utilities/load-plans/{id}/import-oms-order

从 OMS 销售订单一键导入货物清单(零录入),任一 SKU 缺包装尺寸则 400 并列出 SKU,导入为覆盖写入

POST/api/utilities/load-plans/{id}/items

批量加货到装载方案(一次 ≤1000 行,尺寸单位米、重量 kg),加货后方案状态回退 draft、旧计算结果作废

GET/api/utilities/load-plans/{id}/loading-guide

装柜指导单(仓库现场用),每柜按装柜顺序排列货物摆放 + 3D 数据/重心/利用率 + 可直接打印的 HTML

Landed Cost Scenarios/api/utilities/landed-cost-scenariosGETPOSTPUTDELETE4 个接口

GET/api/utilities/landed-cost-scenarios

到岸成本计算器已保存方案列表(租户级),按更新时间倒序

POST/api/utilities/landed-cost-scenarios

到岸成本计算器新建方案,同租户同名返回 409

DELETE/api/utilities/landed-cost-scenarios/{id}

删除本租户的一条到岸成本方案

PUT/api/utilities/landed-cost-scenarios/{id}

更新到岸成本方案(改名/改内容至少其一),同租户同名返回 409

Bol Scenarios/api/utilities/bol-scenariosGETPOSTDELETE3 个接口

GET/api/utilities/bol-scenarios

BOL 生成器草稿/模板列表(租户级),按更新时间倒序返回表单全量快照

POST/api/utilities/bol-scenarios

BOL 生成器保存草稿/模板,同租户同工具同名返回 409

DELETE/api/utilities/bol-scenarios/{id}

删除本租户的一条 BOL 草稿/模板(仅限 bol-generator/bol-template 工具,防止误删其他工具的方案)

Container Types/api/utilities/container-typesGETPOSTPATCH3 个接口

GET/api/utilities/container-types

集装箱柜型列表,系统预置柜型 + 本租户自定义柜型(默认只返回启用中的)

POST/api/utilities/container-types

新建租户自定义柜型(尺寸单位米、重量 kg),code 在本组织内唯一

PATCH/api/utilities/container-types/{id}

修改租户自定义柜型,系统预置柜型不允许改(403),他组织的柜型不可见(404)

Bol Address Book/api/utilities/bol-address-bookGETPOST2 个接口

GET/api/utilities/bol-address-book

BOL 生成器地址簿,合并返回客户主数据的官方地址(置顶只读)和租户级快捷地址(按使用次数倒序)

POST/api/utilities/bol-address-book

BOL 地址簿新增快捷地址(同名+同电话去重),或点选地址时 use_count+1

Webhooks1 个接口

Payments/api/webhooks/paymentsPOST1 个接口

POST/api/webhooks/payments/{provider}

支付通道 webhook 单端点(D79 §10.2 路由,R-1 首个 provider=stripe;无需登录,验签即鉴权)。按 provider 经注册表查表分发,Stripe-Signature 验签失败回 400;事件只驱动 platform_payments 状态迁移(终态不回退、重投幂等);落 succeeded 前以本地行金额复核,金额不符 → 写 platform_billing_recon_exceptions(payment_vs_provider)+告警、不推进状态;未知支付回 200 并告警

{Token}1 个接口

{Token}/track/{token}GET1 个接口

GET/track/{token}

客人单据进度页(D75 件一,公开无登录):HMAC 签名链接(30 天/终态+7 天失效)→GUEST_DOC_RESOLVERS 只读脱敏视图(一期 intake_case/sales_order);已登录同组织成员 302 跳内部详情;渠道关闭回中性暂停页;点击落审计并回填已查看计数。页面不显示任何 UUID。

Webhooks

事件

事件说明
order.created销售订单创建时触发(手工录入、货主门户下单或 CRM 商机转单)。data: order_id, order_no, status, client_id, warehouse_id, total, currency, channel_order_no。**含 draft 状态(2026-10-27 注记,REQ-20261027-05)**:建单落库即触发,`status` 恒为创建时状态——手工建单与 Rollie 对话建单(经内部执行端点,见「Rollie 第二层写操作一期」节)落的都是 `draft`,订阅方不得把 `order.created` 当作「正式单已生效」,须按 `data.status` 过滤后再处理
order.allocated销售订单完成分配、库存已为该订单锁定时触发。data: order_id, order_no, status, client_id, warehouse_id, total, currency
order.fulfilled销售订单全部履约时触发(OMS 直发或经 WMS 出库单发运)。data: order_id, order_no, status, client_id, warehouse_id, total, currency, tracking_number, carrier_code
order.cancelled销售订单取消时触发。data: order_id, order_no, status, client_id, warehouse_id, cancel_reason_code
order.delivered销售订单标记送达时触发。data: order_id, order_no, status, client_id, warehouse_id, tracking_number, carrier_code
shipment.fulfilledWMS 出库单交运时触发(包裹已交给承运商)。data: shipment_id, shipment_no, order_id, warehouse_id, carrier, tracking_number, order_type
receipt.completed入库单完成收货时触发(全部明细行收完)。data: receipt_id, receipt_no, warehouse_id, status
inventory.adjusted库存被直接调整时触发(库位数量修正)。data: item_id, sku, warehouse_id, location_id, pallet_id, qty_delta, qty_after, reason
invoice.issued应收发票生成时触发(手工新建或由销售单自动生成),新发票为草稿,当前状态见 data.status。data: invoice_id, invoice_no, client_id, status, total, currency, source_type, source_id
delivery.completed尾程配送单签收完成时触发(已留签收凭证)。data: delivery_id, delivery_no, route_id, status, delivered_at, pod_method
test.ping测试事件,任意订阅可随时发送,用于验证接收地址连通与验签是否正确。data: message, subscription_id, subscription_name

签名验证

Docklify 以 POST JSON 向订阅地址投递事件,信封为 {id, type, created_at, organization_id, data},其中 id 是事件幂等 id,同一事件重发时保持不变,订阅方应按 id 去重。每条投递带三个 header:X-Docklify-Event 是事件类型,X-Docklify-Delivery 是本次投递 id,X-Docklify-Signature 形如 t=<unix 秒>,v1=<hex>。v1 的算法是 HMAC-SHA256(secret, "<t>.<原文 body>") 后取 hex,secret 是订阅创建时生成的 whsec_ 开头的签名密钥,可在 Integration → Webhooks 管理页或管理 API 中复看与轮换。验签必须用收到的原文 body 计算,切勿把 JSON 解析后重新序列化,否则字段顺序与空格变化会让签名对不上。Node 一行验签:`const v1 = require('crypto').createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex')`;Python 一行验签:`v1 = hmac.new(secret.encode(), (t + '.' + raw_body).encode(), hashlib.sha256).hexdigest()`,算出的 hex 与 header 里的 v1 一致即验签通过。投递超时为 10 秒,接收端返回 2xx 视为成功;3xx 不跟随跳转、按失败处理,失败后按 1 分钟、5 分钟、30 分钟、2 小时、6 小时退避自动重试,连同首次共 6 次尝试,仍失败则标记为失败,可在投递日志中人工重发。订阅地址必须使用 https,且域名须解析到公网地址,解析到内网或回环地址会被拒绝。任意订阅可随时发送 test.ping 测试事件验证连通与验签,测试事件不要求订阅勾选任何事件。