WMS 集成指南:REST、Webhook 与 WebSocket,如何把数据送上实时仓库地图
WMS 集成用 REST、Webhook 还是 WebSocket?把 WMS 数据送上实时 3D 仓库地图的三种接入方式:REST 轮询、文件上传,以及由你的中转服务调用的表格写入 API。


简短回答
REST、Webhook 还是 WebSocket:你真正要选的是什么
搜“WMS 集成”,你会掉进一场协议之争。对实时仓库地图来说,真正有用的问题更具体:你的 WMS 怎么交出数据?地图需要多新的数据? WMS 可能提供 REST 接口、触发 Webhook、发布到消息队列,或通过 socket 推流。Spatial Map 只接受三类输入:拉取 REST 接口、导入文件、以表格 API 写入的形式接收推送。那么,你需要 Webhook 或 WebSocket 吗?你的 WMS 可能会发出它们;Spatial Map 通过你自己掌控的中转服务,以表格 API 写入的方式接收。
| 仓库数据 | 需要的新鲜度 | 进入 Spatial Map 的路径 |
|---|---|---|
| 各库位的占用和库存 | 约一分钟 | 表格开启 Pull from a REST API(每 30 秒或更长),或由中转服务在变化时推送 |
| 拣货、移库、退货事件 | 秒级 | 中转服务 → 每隔几秒 `POST /rows/bulk` |
| 库位状态变化(锁定、预留、拣货中) | 秒级 | 中转服务 → 对已有行 `PATCH /rows/bulk` |
| 来自 RTLS 的叉车或人员位置 | 几秒 | 中转服务缓冲数据流、批量发送 —— 绝不每个定位点发一次请求 |
| 循环盘点或日终快照 | 每日 | Upload file 加 Re-import,或每晚由脚本调用表格 API |
| 主数据(SKU、区域、月台门) | 变化时 | Upload file,或一次性的批量写入 |
四种数据入口
打开 Integrations → Add integration,有三个选项:REST API、Upload file 和 Table。表格还附带第四条路 —— 它自己的写入 API —— 以及一个可选的服务端轮询器。四者最大的区别在于运行位置。
| 路径 | 在哪里运行 | 新鲜度 | 注意事项 |
|---|---|---|---|
| REST API 集成 | 在打开地图(或 Integrations 页面)的那个人的浏览器里。同步方式 Manually、When a map opens 或 On a timer | 每次同步时更新;定时器只在有地图打开时重复 | WMS API 必须允许应用的来源(CORS),否则会看到 “Your browser is blocked from this API” |
| 表格 · Pull from a REST API | 在 Spatial Map 服务器上,于表格的 API & access 标签页配置 | 间隔不少于 30 秒;轮询器每分钟检查一次,所以按约一分钟预期 | 每次最多 1,000 行、10 MB、30 秒;URL 必须能从公网访问 |
| Upload file | 你本人,在导入对话框中(File、Mode、Match、Mapping、Preview) | 每次重新导入时 | CSV、Excel、JSON 或 GeoJSON —— 适合快照,不适合事件 |
| 表格写入 API | 你的系统用 `sgv_tbl_` 密钥调用 `https://app.spatialmap.io/api/v1/public/tables/…` | 秒级 —— 每次写入都会刷新已打开的地图 | 每个密钥每分钟 60 次(突发 30 次);每次批量调用最多 1,000 行 |
哪条路径适合你的 WMS
你不需要任何厂商专用连接器 —— Spatial Map 也没有。关键是你的 WMS 提供哪种接口。请查阅你所用版本的集成文档;下面的模式适用于大多数产品。
| WMS 类型 | 通常提供什么 | 合适的路径 |
|---|---|---|
| 带事件或集成层的企业级套件 | 读取 API(REST 或 OData),外加发布到集成平台或消息总线的业务事件 | 变化慢的状态用服务端 Pull from a REST API;订阅事件的中转服务用 `/rows/bulk` 写入变更 |
| 带 REST 和外发 Webhook 的云端 WMS | REST 接口,以及按事件类型配置的 Webhook(任务完成、库位锁定、订单下发) | 把 Webhook 指向你的中转服务(一个 serverless 函数就够),批量写入表格 API;用 REST 拉取做对账 |
| 部署在防火墙后的本地 WMS | 接口只在内网可达 | 把中转服务部署在内网,它只需要能向外访问表格 API 的 HTTPS。服务端轮询无法访问内网 URL |
| 老旧系统或自研系统 | 一个数据库、定时导出的平面文件,有时有一层简单的 REST | 导出文件用 Upload file 加 Re-import,或用定时脚本读库后写入表格 API |
用一个小型中转服务桥接 Webhook、队列和 socket
中转服务就是位于 WMS 与 Spatial Map 之间的任何小程序:挂在 WMS Webhook 后面的 serverless 函数、消息队列的消费者,或保持 RTLS socket 连接的进程。它的工作永远一样 —— 把每个事件转成一行表格数据,再批量发送。
- 1创建表格
在 Tables 中按事物类型各建一张表(库位、拣货事件、人员),并选择类型 —— Marker / POI、Asset (mobile)、Shipment、Polygon / area 等。每个字段都有一个 API key,例如 `bin_code` 或 `status`:这就是中转服务要发送的 payload 键。参见 Tables。
- 2创建密钥
在表格的 API & access 标签页,由 Owner 或 Admin 创建密钥。密钥以 `sgv_tbl_` 开头,只显示一次。一个密钥只能写一张表,所以 URL 里没有表格 ID。给每个系统单独的密钥,吊销其中一个不会影响其他;并从同一标签页复制准确的基础 URL。
- 3把每个事件映射成一行
选一个稳定的 `entityKey` —— 库位编码、事件 ID、工牌 ID。行按这个键做 upsert,重复投递会覆盖而不是产生重复。
- 4批量发送,不要逐条发
缓冲几秒后,一次发送 `POST /rows/bulk`(完整行)或 `PATCH /rows/bulk`(仅变更字段),最多 1,000 行。即使部分行失败,有效行照样提交;被拒的行在 `errors[]` 中返回。
- 5对正确的错误重试
`429` 表示密钥超过每分钟 60 次;`401` 表示密钥错误或已吊销;`400` 表示某行违反表格结构(必填或唯一字段)。保留未发送的行,下一轮再发。
curl -X POST https://app.spatialmap.io/api/v1/public/tables/rows \
-H "Authorization: Bearer $SPATIALMAP_TABLE_KEY" \
-H "Content-Type: application/json" \
-d '{"entityKey":"EV-20261011-0412","payload":{"event_id":"EV-20261011-0412","event_type":"pick","item_id":"B-B86-L2-01","from_bin_code":"B-B86-L2","quantity":2,"worker_id":"W-04","ts":"2026-10-11T09:14:05Z"}}'curl -X POST https://app.spatialmap.io/api/v1/public/tables/rows/bulk \
-H "Authorization: Bearer $SPATIALMAP_TABLE_KEY" \
-H "Content-Type: application/json" \
-d '{"rows":[
{"entityKey":"EV-20261011-0413","payload":{"event_id":"EV-20261011-0413","event_type":"pick","item_id":"A-B07-L1-02","from_bin_code":"A-B07-L1","quantity":1,"worker_id":"W-02","ts":"2026-10-11T09:14:09Z"}},
{"entityKey":"EV-20261011-0414","payload":{"event_id":"EV-20261011-0414","event_type":"move","item_id":"B-B99-L1-03","from_bin_code":"B-B99-L1","to_bin_code":"B-B51-L1","quantity":1,"worker_id":"W-05","ts":"2026-10-11T09:14:11Z"}}
]}'curl -X PATCH https://app.spatialmap.io/api/v1/public/tables/rows/A-B01-L1 \
-H "Authorization: Bearer $SPATIALMAP_TABLE_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"blocked","hold_reason":"Damaged pallet"}'// relay.mjs (Node 18+) - receives bin-status webhooks from your WMS and
// forwards them in batches to the "Rack Inventory" table. A sketch, not a product.
import http from 'node:http';
const BASE = 'https://app.spatialmap.io/api/v1/public/tables'; // copy yours from API & access
const KEY = process.env.SPATIALMAP_TABLE_KEY; // sgv_tbl_... (this table's key)
const pending = new Map(); // bin_code -> latest changes
http.createServer((req, res) => {
let body = '';
req.on('data', (chunk) => (body += chunk));
req.on('end', () => {
try {
// 1. Verify your WMS's webhook signature here (its docs say how).
const e = JSON.parse(body);
// 2. Map the WMS event onto your table's field keys.
const prev = pending.get(e.bin_code)?.patch ?? {};
pending.set(e.bin_code, {
entityKey: e.bin_code,
patch: { ...prev, status: e.status, sku: e.sku, quantity: e.quantity },
});
res.writeHead(202).end();
} catch {
res.writeHead(400).end();
}
});
}).listen(8080);
// 3. Flush every 5 s: one request instead of one per event (60 requests/min per key).
setInterval(async () => {
const rows = [...pending.values()].slice(0, 1000);
if (rows.length === 0) return;
rows.forEach((r) => pending.delete(r.entityKey));
try {
const res = await fetch(BASE + '/rows/bulk', {
method: 'PATCH', // merge changed fields onto existing bins
headers: { Authorization: 'Bearer ' + KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ rows }),
});
if (!res.ok) throw new Error('HTTP ' + res.status); // 401 key, 429 rate limit, 5xx
const { errors } = await res.json(); // rows the table rejected
if (errors?.length) console.warn(errors);
} catch (err) {
// put the batch back without losing newer events; retry on the next tick
rows.forEach((r) => {
const newer = pending.get(r.entityKey);
pending.set(r.entityKey, newer ? { ...newer, patch: { ...r.patch, ...newer.patch } } : r);
});
console.error(err);
}
}, 5000);实战示例:Acme Warehouse
演示仓库 Acme Warehouse 有 17 排货架、314 个库位,配有 Rack Inventory(每个库位一行,以 `A-B01-L1` 这样的 `bin_code` 为键,字段有 `status`、`sku`、`quantity`)、Inventory Items、Pick Events 和 Warehouse Workers 等表格。一个典型的 WMS 数据流会用到四条路径中的三条。
- 1库位状态走轮询
如果 WMS 有按库位查询库存的接口,打开 Rack Inventory → API & access → Pull from a REST API:填写 URL、不少于 30 秒的间隔、Row key field in the response = `bin_code`;如果列表包在外层对象里,填写 Where the items are (JSON path);再配置认证请求头和字段映射。点 Start polling,第一次运行会在一分钟内完成。完整步骤:按计划轮询 REST 接口。
- 2事件走推送
把 WMS 的“拣货确认”和“库位状态”Webhook 指向你的中转服务。确认的拣货成为 Pick Events 中的新行(`POST /rows/bulk`);状态变化则更新 Rack Inventory 中对应的库位(`PATCH /rows/bulk`)。分步说明:用表格写入 API 推送数据行。
- 3快照走上传
每晚的循环盘点导出文件通过 Upload file 导入,在来源卡片上点 Re-import 即可刷新 —— 不用写代码。
- 4画到地图上
在编辑器中打开 Data → Manage data links → New link。Color a shape 链接用样式规则按 `status` 给每个库位着色;Live location marker 链接把人员放到其经纬度位置。参见 数据链接概览。
- 5确认数据在流动
Integrations 下的 Health 标签页列出每张表,以及你的系统最近一次写入的时间。每次 API 写入还会记录在该行的 History 中,可以用 Historical movement 链接在地图上回放。


最常见的坑
延伸阅读
- Tables —— 表结构、记录和 API & access 标签页。
- Integrations —— REST API 集成、文件上传和健康状态。
- 用表格写入 API 推送数据行 —— 带密钥和 curl 的完整示例。
- 按计划轮询 REST 接口 —— 服务端轮询全流程。
- 数据链接概览 —— 表格行如何变成标记、着色和数值徽标。
- Spatial Map 仓库解决方案 与 仓库数字孪生与 WMS 的区别。
让数据落到该在的平台上。
Spatial Map 把电子表格、传感器数据流和 CAD 图纸融合成一张实时的 3D 场地视图 —— 无需安装,七天免费试用。
在线演示
继续阅读
- 教程仓库 KPI 看板 + 实时 3D 地图:报表构建器分步教程图表告诉你 66% 的库位已占用,地图告诉你在哪里。本教程带你走完 12–13 步的引导式报表向导,把两者放进同一个仓库看板 —— 以我们演示仓库中真实的 Rack Inventory 报表为例。
- 教程从表格到地图:把库位库存 CSV 变成实时货架图躺在共享盘里的 CSV 对现场毫无帮助。同一份 CSV 画到货架布局上,就是一次班前会。
- 教程从 CAD 或 PDF 平面图到浏览器 3D 地图:分步指南选好图纸或图层,确认比例或单位,把平面图放到地图上并对齐。图纸以真实尺寸的图片导入;3D 建筑是你在上面描绘出来的。本文讲完整流程,也说明它能做什么、不能做什么。