14 KiB
MotherShip 查询接口调用文档
第三方正式对接请优先阅读:同目录
api对接文档.md(v1.1,四路线:MotherShip/Flock × 免账号/登录后)。
本文档保留 MotherShip 宿主两步 + 管理端接口细项,适合内部运维对照;Flock / 登录后字段以对接文档为准。
本文档说明 MotherShip / Axel 查询报价相关接口(偏免账号宿主两步),适合内部运维对照使用。
Base URL:https://if.dev.51track.vip
统一响应格式:
{ "code": 0, "message": "ok", "data": { } }
code !== 0 为业务/鉴权错误。询价业务失败时 HTTP 可能仍为 200,此时看 data.status === "failed"。
1. 推荐接口(第三方宿主)
当前推荐使用 两步宿主接口(须鉴权):
POST /api/host/quote/candidatesPOST /api/host/quote/submit
特点:
- 第一步返回提货 / 派送地址候选
- 第二步服务端内部等待询价并同步返回最终报价
- 调用方不需要自己轮询
GET /api/quotes/{id}
2. 鉴权(必传)
当前服务器已关闭公开免 Token 模式(HOST_PUBLIC_API_ENABLED=false),每次请求须携带:
Authorization: Bearer <API Key 或 Service Token>
X-Customer-Id: <Customer ID>
Content-Type: application/json
| 字段 | 说明 |
|---|---|
Authorization |
Bearer + 我方发放的凭证 |
X-Customer-Id |
客户 ID,必须与凭证绑定一致 |
Content-Type |
固定 application/json |
2.1 凭证来源(二选一)
| 类型 | 形态 | 来源 |
|---|---|---|
| 客户 API Key(推荐给第三方) | 通常以 chj_ 开头 |
管理端「客户管理」新建客户 / 轮换 Key 后发放 |
| Service Token | 自定义字符串,如 demo-host-token |
服务器 .env 的 HOST_SERVICE_TOKENS(联调/内网) |
第三方正式对接请使用管理端发放的 API Key,不要把 Key 写进前端页面或公开仓库。
2.2 请求头示例
Authorization: Bearer chj_xxxxxxxxxxxxxxxxxxxxx
X-Customer-Id: CUST_003
Content-Type: application/json
联调可用 env Token(若服务器已配置):
Authorization: Bearer demo-host-token
X-Customer-Id: CUST_001
Content-Type: application/json
2.3 鉴权错误
| HTTP | message | 说明 |
|---|---|---|
| 401 | 缺少 Authorization 头 | 未带 Bearer |
| 401 | Service Token 无效 | Key/Token 错误或已轮换失效 |
| 403 | customer_id 与令牌租户不匹配 | X-Customer-Id 与 Key 绑定不一致 |
| 401 | 令牌无效或已过期 | 误用了管理员 JWT,应使用 API Key / Service Token |
2.4 Apifox 环境变量
| 变量 | 示例值 |
|---|---|
baseUrl |
https://if.dev.51track.vip |
token |
管理端发放的 chj_... 或联调 demo-host-token |
customerId |
与 Token 绑定的客户 ID,如 CUST_001 |
Headers:
Authorization:Bearer {{token}}X-Customer-Id:{{customerId}}Content-Type:application/json
3. 第一步:获取联想地址候选
接口
POST /api/host/quote/candidates
请求头
Authorization: Bearer <API Key>
X-Customer-Id: <Customer ID>
Content-Type: application/json
请求体
{
"pickup_address": {
"street": "1234 Warehouse Blvd",
"city": "Los Angeles",
"state": "CA",
"zip": "90001"
},
"delivery_address": {
"street": "5678 Distribution Dr",
"city": "Dallas",
"state": "TX",
"zip": "75201"
},
"cargo": {
"weight": { "value": 500, "unit": "kg" },
"dimensions": { "length": 120, "width": 100, "height": 150, "unit": "cm" },
"pallet_count": 2,
"cargo_type": "general_freight"
}
}
字段说明
| 字段 | 必填 | 说明 |
|---|---|---|
pickup_address |
是 | 提货草稿地址 |
delivery_address |
是 | 派送草稿地址 |
street / city / state |
是 | state 为美国州二字码 |
zip |
否 | 建议传,格式 12345 或 12345-6789 |
cargo.weight.value |
是 | 单托重量 |
cargo.weight.unit |
是 | lb、kg 或 t/tonne(公制吨;禁止 ton/tons) |
cargo.dimensions.* |
是 | 单托长宽高 |
cargo.dimensions.unit |
是 | in、cm 或 m |
cargo.pallet_count |
是 | 托盘数,1–25 |
cargo.cargo_type |
是 | 见下方枚举 |
货物类型 cargo_type:
general_freight · machinery · furniture · electronics · building_materials · auto_parts · food_nonperishable · apparel · other
服务端会自动把 lb/kg/t、in/cm/m 换算为 MotherShip 需要的英制单位(小数进一)。
成功响应示例
{
"code": 0,
"message": "ok",
"data": {
"host_session_id": "2dd352e6-9a1d-4563-8f13-ebff18aabdb9",
"pickup_candidates": [
{
"option_id": "Eisx...",
"display_label": "1234 Warehouse Street, Los Angeles, CA, USA",
"formatted_address": "1234 Warehouse Street, Los Angeles, CA, USA",
"street": "1234 Warehouse Street",
"city": "Los Angeles",
"state": "CA",
"zip": "90001",
"selectable": true
}
],
"delivery_candidates": [
{
"option_id": "EihE...",
"display_label": "Distribution Dr, Wilmer, Dallas, TX, USA",
"formatted_address": "Distribution Dr, Wilmer, Dallas, TX, USA",
"street": "5678 Distribution Dr, Wilmer",
"city": "Dallas",
"state": "TX",
"zip": "75201",
"selectable": true
}
],
"requires_selection": true
}
}
第一步调用后处理
- 保存
data.host_session_id(约 30 分钟有效) - 从
pickup_candidates选 1 条selectable: true - 从
delivery_candidates选 1 条selectable: true - 第二步提交时传回选中的完整候选对象(不要只传
option_id)
不要使用 selectable: false 的候选(可能带 unavailable_reason)。
4. 第二步:提交候选并获取最终报价
接口
POST /api/host/quote/submit
请求头
与第一步相同。
请求体
{
"host_session_id": "2dd352e6-9a1d-4563-8f13-ebff18aabdb9",
"pickup_candidate": {
"option_id": "Eisx...",
"display_label": "1234 Warehouse Street, Los Angeles, CA, USA",
"formatted_address": "1234 Warehouse Street, Los Angeles, CA, USA",
"street": "1234 Warehouse Street",
"city": "Los Angeles",
"state": "CA",
"zip": "90001",
"selectable": true
},
"delivery_candidate": {
"option_id": "EihE...",
"display_label": "Distribution Dr, Wilmer, Dallas, TX, USA",
"formatted_address": "Distribution Dr, Wilmer, Dallas, TX, USA",
"street": "5678 Distribution Dr, Wilmer",
"city": "Dallas",
"state": "TX",
"zip": "75201",
"selectable": true
}
}
注意
host_session_id必须来自第一步- 候选对象必须是第一步列表中的完整对象(
option_id须匹配) - HTTP 连接可能保持 10–420 秒;客户端 / Nginx 超时建议 ≥ 420 秒
- 不会返回
processing让你继续轮询;服务端内部完成等待
成功响应示例
{
"code": 0,
"message": "ok",
"data": {
"quote_id": "QTE_20260630_0003",
"request_id": "xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx",
"status": "done",
"currency": "USD",
"valid_until": "2026-06-30T10:30:00.000Z",
"source_type": "rpa",
"quotes": [
{
"service_level": "standard",
"rate_option": "lowest",
"carrier": "Frontline Freight",
"transit_days": "Est. 5 business days",
"final_total": 337.06
}
]
}
}
| 字段 | 说明 |
|---|---|
status |
done 成功;failed 失败(看 error_message) |
quotes[].final_total |
对客户展示价(USD,含加价) |
quotes[].carrier |
承运商 |
quotes[].transit_days |
时效 |
valid_until |
报价有效期 |
5. 调用步骤总结
- 带鉴权头调
POST /api/host/quote/candidates - 保存
host_session_id,让用户各选一条可用地址 - 带鉴权头调
POST /api/host/quote/submit - 直接展示最终报价
第三方需要做
- API Key 放服务端,不暴露前端
- 每次请求带
Authorization+X-Customer-Id - 第一步做地址选择 UI;第二步 Loading(超时 ≥ 420s)
第三方不需要做
- 不需要
GET /api/quotes/{id}轮询 - 不需要自己做公制 → 英制换算(支持
kg/t/cm/m,服务端统一进一取整为 lb/in)
6. Apifox / cURL
Apifox
| 步骤 | 方法 | URL |
|---|---|---|
| 1 | POST | {{baseUrl}}/api/host/quote/candidates |
| 2 | POST | {{baseUrl}}/api/host/quote/submit |
第二步超时建议:420000 ms。
cURL(第一步)
curl -X POST "https://if.dev.51track.vip/api/host/quote/candidates" \
-H "Authorization: Bearer <API Key>" \
-H "X-Customer-Id: CUST_001" \
-H "Content-Type: application/json" \
--data-binary @host-candidates-req.json
PowerShell(本机测公网,不要写 127.0.0.1,不要加 :30325):
curl.exe -s -w "`nHTTP: %{http_code}`n" `
-X POST "https://if.dev.51track.vip/api/host/quote/candidates" `
-H "Authorization: Bearer demo-host-token" `
-H "X-Customer-Id: CUST_001" `
-H "Content-Type: application/json" `
--data-binary "@deploy/host-candidates-req.example.json"
7. 常见错误
| code | HTTP | 说明 | 处理 |
|---|---|---|---|
UNAUTHORIZED |
401 | 缺少或无效 Token/API Key | 检查 Bearer 与客户绑定 |
FORBIDDEN |
403 | 客户 ID 与令牌不匹配 | 核对 X-Customer-Id |
VALIDATION_FAILED |
400 | 参数不合法 / JSON 无效 | 检查字段、单位、州码 |
SESSION_EXPIRED |
404 | host_session_id 过期 |
重新调第一步 |
ADDRESS_SESSION_MISMATCH |
400 | 候选不在本次联想结果中 | 使用第一步返回的完整对象 |
ADDRESS_NOT_SELECTABLE |
400 | 选了不可用候选 | 改用 selectable: true |
QUOTE_TIMEOUT |
504 | 服务端等待超时 | 稍后重试 |
RATE_LIMITED |
429 | 限流 | 降低频率 |
8. 客户管理接口(管理员)
供管理端 / 内部运维使用,不提供给第三方宿主直接调用。
8.1 鉴权
Authorization: Bearer <Admin JWT>
Content-Type: application/json
管理员 JWT 通过 POST /api/auth/login 获取(账号密码登录)。
8.2 获取客户列表
GET /api/admin/customers?page=1&size=10&keyword=CUST_001
| 参数 | 必填 | 说明 |
|---|---|---|
page |
是 | 页码,从 1 开始 |
size |
是 | 每页 1–100 |
keyword |
否 | 按客户 ID / 名称模糊搜索 |
成功时 data.list[] 主要字段:
| 字段 | 说明 |
|---|---|
customer_id |
客户 ID |
status |
active / disabled |
embed_password_set |
是否已设 /embed-demo 密码 |
active_api_key |
当前有效 API Key;历史未保存原文时可能为 null |
api_keys[] |
Key 摘要(不含完整原文,仅前缀等) |
8.3 新建客户
POST /api/admin/customers
{
"name": "演示客户 003",
"remark": "重点客户",
"embed_password": "123456"
}
| 字段 | 必填 | 说明 |
|---|---|---|
name |
是 | 客户名称 |
remark |
否 | 备注 |
embed_password |
否 | /embed-demo 登录密码;不传默认 123456 |
响应中 api_key 仅在新建时额外返回一次;同时写入 active_api_key。请立即保存发给第三方。
8.4 更新客户
PATCH /api/admin/customers/{customer_id}
可更新:name、remark、status(active/disabled)、embed_password(至少 6 位)。
8.5 轮换 API Key
POST /api/admin/customers/{customer_id}/rotate-key
- 原有效 Key 立即失效
- 响应中的
api_key与active_api_key为新 Key - 轮换后须通知第三方更换凭证
8.6 承运商官网账密(管理端)
GET /api/admin/customers/{customer_id}/provider-credentials
PUT /api/admin/customers/{customer_id}/provider-credentials
用于绑定客户在 MotherShip / Flock 官网的登录账密(RPA 使用),非第三方宿主对接接口。
PUT 请求体示例:
{
"provider": "mothership",
"email": "user@example.com",
"password": "********"
}
| 约束 | 说明 |
|---|---|
provider |
仅 mothership 或 flock |
| 写入策略 | 仅允许首次绑定;已绑定后不可修改 / 清除 |
| 清除 | 不支持 clear;更换需新建客户 |
9. 嵌入演示登录
供 /embed-demo 演示页使用,不是正式宿主 API。
9.1 登录
POST /api/embed-demo/login
{
"customer_id": "CUST_003",
"password": "cust003@2026"
}
- 密码以管理端「客户管理」中为该客户设置的为准
- 成功后写入 HttpOnly Cookie:
embed_demo_session
9.2 当前会话 / 退出
GET /api/embed-demo/me
POST /api/embed-demo/logout
me 依赖登录 Cookie,返回当前客户及加价配置。
10. 其它渠道说明(非推荐宿主对接)
以下接口同样需要 Service Token / API Key,但返回 processing,需客户端轮询,不作为第三方默认同步对接方案:
| 渠道 | 提交 | 轮询 |
|---|---|---|
| MotherShip 旧三步 | POST /api/quotes 等 |
GET /api/quotes/{quote_id} |
| Priority1 | POST /api/priority1/quotes |
同上 |
| Flock | POST /api/flock/quotes |
同上 |
第三方正式对接请优先使用本文档第 1–4 节的两步宿主接口。
11. 联系与支持
- Token / API Key 失效或需开通新客户:联系我方运维 / 管理端操作
X-Customer-Id必须与发放凭证绑定一致,不可串用- 老客户若
active_api_key为空:在管理端「轮换 Key」一次后再查看