开发者文档 · Open API v1

把云打印接入你的业务系统

通过 RESTful 开放 API,在 ERP、WMS、MES 等系统里直接提交打印任务、获取模板和查看打印机状态。所有接口都使用 JSON,用 AppID + AppSecret 鉴权,并按 Scope 精细授权。

Base URL  https://api.varilabel.com/api/open/v1

概览

所有接口都挂在 /api/open/v1 下,请求体和响应体都是 JSON(UTF-8)。服务端按下面的顺序处理每个请求,任何一步被拒绝都会直接返回对应的状态码:

  1. 01凭证鉴权401 / 403
  2. 02QPM 限速429
  3. 03月度配额429 · 仅控制面写操作
  4. 04Scope 校验403
  5. 05业务处理4xx / 5xx

* 月度配额只对控制面的写操作生效。GET 查询和数据面接口(流式追加行)不计配额,但同样受凭证级 QPM 限速。

快速开始

下面的例子演示一条最短的接入链路:选打印机 → 取模板 → 提交任务。示例使用 bash 数组 AUTH 复用鉴权头。

# 1. 在控制台「开放平台 → API 凭证」创建凭证,并勾选所需的 Scope
export VARILABEL_APP_ID="<your-app-id>"
export VARILABEL_APP_SECRET="<your-app-secret>"
BASE="https://api.varilabel.com/api/open/v1"
AUTH=(-H "X-App-Id: $VARILABEL_APP_ID" -H "X-App-Secret: $VARILABEL_APP_SECRET")

# 2. 查询打印机,记下 items[].code(提交任务用的是 printer_code,不是 id)
curl -sS "$BASE/printers" "${AUTH[@]}"
#    可以再调用 /printers/for-print,按 id 确认这台打印机 online=true

# 3. 按槽位编码确认模板条目可以打印(share_code 可以在控制台的企业模板详情中查看)
curl -sS "$BASE/template-shares/by-code/S-7K2M9Q" "${AUTH[@]}"
# → { "share_id": "...", "release_id": "...", "can_print": true, ... }

# 4. 提交打印任务(inline 模式:数据行直接放在请求体里,最多 200 行)
curl -sS -X POST "$BASE/print-jobs" "${AUTH[@]}" \
  -H "Content-Type: application/json" \
  -d '{
    "template_code": "S-7K2M9Q",
    "printer_code": "<printer-code>",
    "upload_mode": "inline",
    "params": { "copies": 1 },
    "rows": [
      { "data": { "sku": "A001", "barcode": "690123456789012345" } }
    ]
  }'
# → 201 { "id": "<job-id>", "job_no": "<job-no>", "status": "pending", ... }

# 5. 轮询任务状态,直到进入终态(completed / partial / failed / cancelled)
JOB_ID="<job-id>"
curl -sS "$BASE/print-jobs/$JOB_ID" "${AUTH[@]}"

鉴权与 Scope

请在控制台的「开放平台 → API 凭证」中创建凭证,拿到 AppID 和 AppSecret。每个请求都要通过请求头带上它们(推荐):

GET /api/open/v1/template-groups HTTP/1.1
Host: api.varilabel.com
X-App-Id: <your-app-id>
X-App-Secret: <your-app-secret>

也可以使用 HTTP Basic Auth,方便 curl 等标准工具调用:

# 等价写法:HTTP Basic Auth(用户名 = AppID,密码 = AppSecret)
curl -sS -u "$VARILABEL_APP_ID:$VARILABEL_APP_SECRET" "https://api.varilabel.com/api/open/v1/template-groups"
  • 妥善保管 AppSecret。只能在服务端使用,不要放进前端页面、App 安装包或代码仓库。
  • 鉴权失败统一返回 401,不区分「AppID 不存在 / 密钥错误 / 凭证停用或过期 / IP 不在白名单」。排查时请把响应头 X-Request-Id提供给我们,我们可以查到具体原因。
  • 轮换密钥:重置密钥后,旧密钥在灰度期内仍然可用,但响应会带上X-Credential-Deprecated: true 和X-Credential-Expires-At(旧密钥失效时间)。建议监控这两个响应头,在旧密钥失效前完成替换。

Scope

每个接口都需要对应的 Scope。创建凭证时请只勾选业务确实需要的 Scope(最小权限原则)。缺少 Scope 的请求会返回403。除 Scope 外,模板等资源还受资源级授权约束:凭证只能看到被授权的分组和条目。

Scope说明涉及接口数
print_job:read读取打印任务、上传进度4
print_job:create提交 / 重试打印任务、流式上传与封口4
print_job:cancel取消打印任务1
template:read读取模板条目、发布记录、模板内容与分组7
printer:read读取打印机列表与详情3
storage:read查看存储用量、文件列表与下载地址4
storage:write上传、确认与删除文件3

数据约定

ID
所有 ID 都是 64 位整数,在 JSON 里以字符串返回(如 "1938475610293847552")。请按字符串存储,不要转成 JavaScript number,否则会丢失精度。
请求中的 ID
请求体里的 ID 字段(如 template_release_id、source_file_id)同样必须传字符串。传成 JSON 数字会返回400 invalid_field_type。
请求体
必须是恰好一个 JSON 对象。未定义的字段会被静默忽略,不会报错,请对照接口参考核对字段名(例如提交任务用template_code,不是 share_code)。
打印数据中的数字
条码、批号、编码等请以字符串传递(如 "0690123456789")。JSON 数字无法表达前导 0,也容易在你自己的系统里被转成浮点数而丢失精度。
时间
RFC 3339 格式,带时区偏移,如2025-01-01T10:00:00+08:00。
分页
Query 参数 page(从 1 开始)和page_size(默认 20,最大100,超出会按最大值处理)。响应统一为{ items, total, page, page_size }。
尺寸
width /height 是数字,单位由size_unit 决定:mm、cm、in、px。其中 px 指 CSS 像素(1px = 1/96 英寸),不是打印机点(dot)。
可空字段
没有值的字段有两种表现:模板接口返回 null,打印机和打印任务接口直接省略这个字段。各接口的数据结构里都有标注,请两种情况都做好判断。
临时地址
封面图、文件下载地址都是带签名的临时 URL,附带expires_at。请在过期前重新拉取,不要长期保存 URL。

限速与配额

凭证级 QPM 限速

按凭证计算每分钟请求数,默认 60 次/分钟,企业版可以调高。所有接口(包括 GET 和数据面)都受限速约束。被限速拒绝的请求不消耗月度配额。

月度调用配额

只有控制面的写操作(POST / DELETE)消耗套餐的月度配额,每次 1 次。GET 查询(包括轮询任务状态)和流式追加行/rows 不计配额。配额按自然月重置。

请求类型月度配额
GET 查询(列表、详情、进度、模板内容)不计
POST / DELETE(提交、重试、取消、封口、上传、删除)每次 1 次
POST /print-jobs/:id/rows不计
被 QPM 限速拒绝的请求不计
写请求被 Scope 校验等业务规则拒绝(4xx)计 1 次
服务端返回 5xx 的请求自动退还

* Scope 校验在月度配额之后执行,所以缺少 Scope 的写请求也会消耗 1 次配额。打印任务另外还有按月计算的标签额度和任务数额度,用尽时返回 403(label_quota_exceeded / print_quota_exceeded),见打印任务对接指南。

响应头

  • X-RateLimit-Limit:当前窗口的请求上限
  • X-RateLimit-Remaining:当前窗口的剩余次数
  • X-RateLimit-Reset:窗口重置时间(Unix 秒)
  • Retry-After:被拒绝时建议等待的秒数
  • X-RateLimit-Mode: degraded:限速服务处于降级模式,计数精度较低,限额不变
  • X-Quota-Limit:套餐的月度配额上限(不限量的套餐不返回)
  • X-Quota-Period:本次请求计入的月份(只在计费请求上返回)

超过 QPM 限速

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1735689600
Retry-After: 42

{
  "code": "TOO_MANY_REQUESTS",
  "message": "请求频率超过凭证限制,请稍后重试"
}

月度配额用尽

同样返回 429,但错误码是 API_QUOTA_EXCEEDED。这种情况重试永远不会成功,请升级套餐或等到 reset_at。

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-Quota-Limit: 1000
X-Quota-Period: 2025-01
Retry-After: 1209600

{
  "code": "API_QUOTA_EXCEEDED",
  "message": "本月 API 调用配额已用尽,请升级套餐或等待下月重置",
  "data": {
    "month": "2025-01",
    "limit": 1000,
    "reset_at": "2025-02-01T00:00:00+08:00"
  }
}

建议:根据 code 区分两种 429,只对TOO_MANY_REQUESTS 按Retry-After 退避重试;批量场景请自己控制并发,不要无限重试。

错误处理

出错时返回非 2xx 状态码,响应体包含机器可读的 code 和可读的 message,部分错误还会带上data:

{
  "code": "not_found",
  "message": "template share not found"
}

请用「HTTP 状态码 + code」做判断,code 按完整字符串精确匹配。message 只供人阅读,内容可能调整。

状态码code含义建议处理
400invalid_parameterinvalid_requestinvalid_jsoninvalid_field_type请求参数或请求体不合法。打印任务接口还会返回更具体的 code(如 upload_mode_required、row_no_mixed),见各接口说明修正后再调用,不要自动重试
401UNAUTHORIZED凭证缺失或无效:AppID 不存在、密钥错误、凭证已停用或过期、IP 不在白名单(统一返回,不区分具体原因)检查凭证配置;联系支持时提供响应头 X-Request-Id
403FORBIDDENforbiddenpermission_denied工作空间已禁用、当前套餐不含 OpenAPI、凭证缺少接口所需的 Scope,或无权访问该资源按 message 处理,不要重试
403label_quota_exceededprint_quota_exceeded本月标签额度或打印任务数额度用尽。它们和 API 调用配额是不同的额度重试不会成功:升级套餐,或等到下个月
404not_found资源不存在、不属于当前企业,或当前凭证无权查看(不区分)检查 ID 和凭证授权范围
409share_not_listednot_retryablerows_mismatch…资源状态冲突见各接口的错误说明
410endpoint_removeddata_purged接口已下线,或打印数据已过保留期被清理按迁移指引改用新接口;数据已清理的任务只能重新提交
413payload_too_largeinline_payload_too_large请求体过大缩小单次请求;大批量数据请用 streaming 模式
429TOO_MANY_REQUESTS触发凭证级 QPM 限速按 Retry-After 退避后重试
429API_QUOTA_EXCEEDED本月调用配额已用尽重试不会成功:升级套餐,或等到 data.reset_at
502data_write_failed打印任务已创建,但数据行写入失败;任务已被标记失败并清理直接重新提交,不会重复打印
5xxinternal_error服务端异常GET 请求可以指数退避重试;POST /print-jobs 不幂等,重试前先查询确认任务是否已经创建。这类请求不消耗月度配额

模板对接指南

对外接口只开放企业模板库。理解下面四个概念,就能理解所有模板接口:

分组group

企业模板库的分类。可以按分组给凭证授权。

条目share

某个模板在某个分组里的固定槽位。share_id 和 share_code 在条目的整个生命周期内不变。同一模板发布到两个分组,就是两个条目。

发布记录release

条目的一次正式生效(审核通过、免审直发或管理员回滚)。它固定了版本以及名称、尺寸等快照,只增不改。

内容content

发布记录对应的模板设计内容,附带 SHA-256 内容指纹 content_hash。

企业侧只认发布记录。作者在个人库里修改、禁用或归档模板,都不会影响已经生效的条目。只有新版本审核通过(或在免审分组直接发布),或者管理员执行回滚,条目的 release_id 才会变化。产线不会因为作者的一次误操作而受影响。

推荐流程

  1. 1

    授权

    在控制台把模板发布到分组,给凭证授予该分组(或单个条目)的访问权限,并勾选 template:read。

  2. 2

    保存 share_code

    在业务系统的配置里保存条目的 share_code(S-XXXXXX),不要保存模板 ID。

  3. 3

    定位条目

    运行时调用 GET /template-shares/by-code/:shareCode,拿到 share_id、当前 release_id 和 can_print。

  4. 4

    获取内容

    调用 GET /template-shares/:shareId/content。同一 release_id 的内容永远不变,可以按 release_id 或 content_hash 缓存。

  5. 5

    历史补打

    先用 GET /template-shares/:shareId/releases 找到当时的发布记录,再调用 content?release_id= 取当时的内容。

export VARILABEL_APP_ID="<your-app-id>"
export VARILABEL_APP_SECRET="<your-app-secret>"
BASE="https://api.varilabel.com/api/open/v1"
AUTH=(-H "X-App-Id: $VARILABEL_APP_ID" -H "X-App-Secret: $VARILABEL_APP_SECRET")

# ① 按槽位编码定位条目,拿到 share_id 与当前 release_id
curl -sS "$BASE/template-shares/by-code/S-7K2M9Q" "${AUTH[@]}"
SHARE_ID="<share-id>"

# ② 获取当前生效的模板内容(同一 release_id 的内容不会变化,可以缓存)
curl -sS "$BASE/template-shares/$SHARE_ID/content" "${AUTH[@]}"

# ③ 历史补打:先查发布记录,再按 release_id 取当时的内容
curl -sS "$BASE/template-shares/$SHARE_ID/releases?page=1&page_size=20" "${AUTH[@]}"
RELEASE_ID="<release-id>"
curl -sS "$BASE/template-shares/$SHARE_ID/content?release_id=$RELEASE_ID" "${AUTH[@]}"
  • • 模板接口都是 GET,不消耗月度配额,但受 QPM 限速。建议按 release_id 缓存内容,不要每次打印前都重新拉取。
  • • 同一模板发布到多个分组时是多个条目,版本可能不同。请用 share_id 或 share_code 区分,不要用模板名称。
  • • 条目下架后,按 share_id / share_code 查询都会返回 404。重新上架后,原来的 share_id 和 share_code 会恢复可用。

大批量流式上传

数据超过 200 行或 512 KiB 时,请使用 streaming 模式。单个任务最多2,000,000 行。

  1. 1

    创建任务

    POST /print-jobs,upload_mode=streaming,并声明 rows_expected(总行数)。计 1 次 API 配额。

  2. 2

    分批追加

    多次调用 POST /print-jobs/:id/rows,每批最多 1,000 行,每行带全局 row_no(1..rows_expected)。批次可以乱序。不计月度配额,但受 QPM 限速。

  3. 3

    断点续传

    中断后调用 GET /print-jobs/:id/upload-progress 查看 rows_uploaded 和 max_row_no,从缺少的行继续。重传已写入的行是安全的:它们会计入 duplicated,不会覆盖原数据。

  4. 4

    封口

    POST /print-jobs/:id/seal。服务端校验行数等于 rows_expected,且 row_no 连续无缺口,通过后立即开始下发。重复封口返回 200。

注意:
  • • 没有封口的 streaming 任务永远不会下发打印。
  • • row_no 是全局行号,不要每批都从 1 开始:否则第二批起会全部计入 duplicated 并被丢弃,最后封口时报 rows_mismatch。首次上传时 duplicated 大于 0,就说明行号算错了。
  • • 长时间没有追加活动的未封口任务,会被平台判定为上传中断并标记为失败。不再继续上传时,请主动调用 cancel 释放预留的标签额度。
  • • 按默认 60 次/分钟计算,传满 2,000,000 行至少需要约34 分钟,而且轮询等其他请求也占用同一个 QPM 配额。需要更快时请联系我们调高 QPM。
export VARILABEL_APP_ID="<your-app-id>"
export VARILABEL_APP_SECRET="<your-app-secret>"
BASE="https://api.varilabel.com/api/open/v1"
AUTH=(-H "X-App-Id: $VARILABEL_APP_ID" -H "X-App-Secret: $VARILABEL_APP_SECRET")

# ① 创建 streaming 任务,声明总行数(计 1 次 API 配额)
curl -sS -X POST "$BASE/print-jobs" "${AUTH[@]}" \
  -H "Content-Type: application/json" \
  -d '{
    "template_code": "S-7K2M9Q",
    "printer_code": "<printer-code>",
    "upload_mode": "streaming",
    "rows_expected": 2000000,
    "params": { "copies": 1 }
  }'
# → 201 { "id": "<job-id>", "status": "pending", "data_sealed": false, ... }
JOB_ID="<job-id>"

# ② 分批追加(不计月度配额,受 QPM 限速)
#    row_no 是全局行号:第 1 批 1..1000,第 2 批 1001..2000,以此类推
curl -sS -X POST "$BASE/print-jobs/$JOB_ID/rows" "${AUTH[@]}" \
  -H "Content-Type: application/json" \
  -d '{
    "rows": [
      { "row_no": 1, "data": { "sku": "A000001" } },
      { "row_no": 2, "data": { "sku": "A000002" }, "copies": 2 }
    ]
  }'
# → { "inserted": 2, "duplicated": 0, "next_row_no": 3, "rows_uploaded": 2 }

# ③ 中断后续传:先确认已经写入到哪一行(GET,不计配额)
curl -sS "$BASE/print-jobs/$JOB_ID/upload-progress" "${AUTH[@]}"
# → { "rows_expected": 2000000, "rows_uploaded": 1000, "max_row_no": 1000, "sealed": false }

# ④ 全部传完后封口(计 1 次 API 配额)。封口成功后立即开始下发
curl -sS -X POST "$BASE/print-jobs/$JOB_ID/seal" "${AUTH[@]}"

# 上传放弃时请取消任务,释放预留的标签额度
curl -sS -X POST "$BASE/print-jobs/$JOB_ID/cancel" "${AUTH[@]}"

接口参考

下面的路径都相对于 https://api.varilabel.com/api/open/v1。带计配额的接口每次调用消耗 1 次月度配额(服务端 5xx 除外)。点击「参数与响应」可以展开详情。存储接口的字段说明正在补充中。

流式上传

只用于 upload_mode=streaming 的任务。提交后分批追加数据行,全部传完后封口,任务才会开始下发。单个任务最多 2,000,000 行。

  • •row_no 是整个任务内的全局行号(1..rows_expected),不是每批都从 1 开始。每批从 1 开始的话,第二批会全部被当作重复行丢弃。
  • •重传是安全的:已经写入的 row_no 会计入 duplicated,不会被覆盖。这也意味着已经写入的行不能再通过重传修改。
  • •批次可以乱序上传,但封口时 1..rows_expected 必须完整、没有缺口。
  • •/rows 不计月度配额,但和其他接口一起受凭证级 QPM 限速。按默认 60 次/分钟、每批 1,000 行计算,传满 2,000,000 行至少需要约 34 分钟。
  • POST/print-jobs/:id/rowsprint_job:create不计配额

    追加数据行

    只对未封口的 streaming 任务有效。不计月度配额,但受 QPM 限速。

    参数与响应

    参数

    名称位置类型说明
    id*路径string任务 ID

    请求体 · AppendRowsRequest

    {
      "rows": [
        {
          "row_no": 1001,
          "data": {
            "sku": "A001001"
          }
        },
        {
          "row_no": 1002,
          "data": {
            "sku": "A001002"
          },
          "copies": 2
        }
      ]
    }

    响应 · AppendResult

    {
      "inserted": 2,
      "duplicated": 0,
      "next_row_no": 1003,
      "rows_uploaded": 1002
    }

    错误

    • 400 invalid_request — rows 为空
    • 400 append_rows_too_many — 单批超过 1,000 行
    • 400 row_no_required — 有行没有给 row_no,或 row_no ≤ 0
    • 400 row_no_duplicated — 同一批内 row_no 重复
    • 400 row_no_out_of_range — row_no 不在 [1, rows_expected] 范围内
    • 400 copies_invalid — 份数为负
    • 400 copies_too_many — 份数超过 1,000
    • 409 rows_exceed_expected — 累计行数会超过提交时声明的 rows_expected
    • 409 job_not_streaming — 任务不是 streaming 模式
    • 409 no_data_expected — 任务以 upload_mode=none 提交,不接受数据行
    • 409 job_not_appendable — 任务已取消、已失败或已封口,不再接受数据
    • 409 job_already_sealed — 任务已封口
  • POST/print-jobs/:id/sealprint_job:create计配额

    封口任务,开始下发打印

    服务端校验实际行数等于 rows_expected,且 row_no 连续没有缺口,通过后立即尝试下发。对已封口的任务重复调用返回 200。响应是任务的最新状态。

    参数与响应

    参数

    名称位置类型说明
    id*路径string任务 ID

    请求体(可省略) · SealRequest(可选)

    {
      "checksum": "<optional-checksum>"
    }

    响应 · PrintJob

    {
      "id": "1938475610293890001",
      "job_no": "<job-no>",
      "status": "pending",
      "source": "api",
      "template_id": "1938475610293800001",
      "template_version_id": "1938475610293810001",
      "template_release_id": "1938475610293850112",
      "virtual_printer_id": "1938475610293860001",
      "terminal_id": "1938475610293870001",
      "upload_mode": "streaming",
      "data_sealed": true,
      "data_purged": false,
      "rows_total": 2000000,
      "rows_printed": 0,
      "rows_failed": 0,
      "total_pages": 2000000,
      "pages_printed": 0,
      "retry_count": 0,
      "max_retry": 3,
      "retryable": false,
      "created_at": "2025-01-01T10:00:00+08:00"
    }

    错误

    • 409 rows_mismatch — 已上传行数不等于 rows_expected。先查 upload-progress,补齐缺少的行后再封口
    • 409 rows_not_continuous — row_no 有缺口(如 1..99、101)
    • 409 job_not_streaming — 任务不是 streaming 模式
    • 404 not_found — 任务不存在
  • GET/print-jobs/:id/upload-progressprint_job:read

    查询上传进度

    网络中断后,用它确认数据已经写入到哪一行,再从断点续传。

    参数与响应

    参数

    名称位置类型说明
    id*路径string任务 ID

    响应 · UploadProgress

    {
      "id": "1938475610293890001",
      "rows_expected": 2000000,
      "rows_uploaded": 1002,
      "max_row_no": 1002,
      "sealed": false
    }

    错误

    • 404 not_found — 任务不存在

数据结构

AppendRowsRequest

字段类型说明
rows*SubmitRow[]本批数据行,1 ~ 1,000 行。每行必须带 row_no(> 0)

AppendResult

字段类型说明
insertedinteger本批新写入的行数
duplicatedinteger本批中已经存在的行号数量。这些行不会被覆盖。重传时出现是正常的;首次上传出现,说明 row_no 算错了
next_row_nointeger本批最大 row_no + 1。只在按顺序上传时有参考意义
rows_uploadedinteger任务累计已写入的行数

UploadProgress

字段类型说明
idstring任务 ID
rows_expectedinteger提交时声明的总行数
rows_uploadedinteger已写入的行数
max_row_nointeger已写入的最大行号。等于 rows_uploaded 时说明 1..max_row_no 没有缺口
sealedboolean是否已封口

SealRequest

请求体可以省略。

字段类型说明
checksumstring可选。客户端计算的数据指纹,只存档用于对账,服务端不校验

模板

企业侧按「条目」(template share)寻址模板,可以用 share_id,也可以用槽位编码 share_code(S-XXXXXX)。所有展示字段和内容都来自已生效的发布记录。概念和推荐流程见「模板对接指南」。

  • GET/templatestemplate:read

    查询当前凭证可访问的全部模板条目

    包括按分组授权和按单个条目授权的条目。同一模板发布到两个分组时,会返回两个条目,它们的版本可能不同。

    参数与响应

    参数

    名称位置类型说明
    nameQuerystring按模板名称筛选
    tagsQuerystring[]按标签筛选,可以重复传:tags=a&tags=b
    statusQueryinteger已废弃只为兼容旧集成保留:不传或传 1 时正常返回,传其他值返回 400。include_inactive 会被忽略。
    pageQueryinteger页码,从 1 开始,默认 1
    page_sizeQueryinteger每页条数,默认 20,最大 100

    响应 · 分页列表<TemplateItem>

    {
      "items": [
        {
          "share_id": "1938475610293847552",
          "group_id": "1938475610293840001",
          "share_code": "S-7K2M9Q",
          "release_id": "1938475610293850112",
          "version_no": 3,
          "name": "发货标签 100×150",
          "description": null,
          "width": 100,
          "height": 150,
          "size_unit": "mm",
          "source": 1,
          "released_at": "2025-01-01T10:00:00+08:00",
          "thumbnail": {
            "url": "https://<oss-domain>/<signed-path>",
            "expires_at": "2025-01-01T11:00:00+08:00"
          },
          "can_print": true
        }
      ],
      "total": 1,
      "page": 1,
      "page_size": 20
    }

    错误

    • 400 invalid_parameter — status 传了 1 以外的值
  • GET/template-shares/by-code/:shareCodetemplate:read

    按槽位编码获取模板条目

    推荐:业务系统只保存 share_code。条目下架、重新上架、更新版本或回滚后,share_code 都不变。拿到 share_id 后,再用它调用发布记录和内容接口。

    参数与响应

    参数

    名称位置类型说明
    shareCode*路径string槽位编码,格式 S-XXXXXX,最长 16 个字符

    响应 · TemplateItem

    {
      "share_id": "1938475610293847552",
      "group_id": "1938475610293840001",
      "share_code": "S-7K2M9Q",
      "release_id": "1938475610293850112",
      "version_no": 3,
      "name": "发货标签 100×150",
      "description": null,
      "width": 100,
      "height": 150,
      "size_unit": "mm",
      "source": 1,
      "released_at": "2025-01-01T10:00:00+08:00",
      "thumbnail": {
        "url": "https://<oss-domain>/<signed-path>",
        "expires_at": "2025-01-01T11:00:00+08:00"
      },
      "can_print": true
    }

    错误

    • 400 invalid_parameter — share_code 为空或超过 16 个字符
    • 404 not_found — 条目不存在、已下架或无权查看(不区分具体原因)
  • GET/template-shares/:shareIdtemplate:read

    获取模板条目详情

    参数与响应

    参数

    名称位置类型说明
    shareId*路径string条目 ID(share_id)

    响应 · TemplateItem

    {
      "share_id": "1938475610293847552",
      "group_id": "1938475610293840001",
      "share_code": "S-7K2M9Q",
      "release_id": "1938475610293850112",
      "version_no": 3,
      "name": "发货标签 100×150",
      "description": null,
      "width": 100,
      "height": 150,
      "size_unit": "mm",
      "source": 1,
      "released_at": "2025-01-01T10:00:00+08:00",
      "thumbnail": {
        "url": "https://<oss-domain>/<signed-path>",
        "expires_at": "2025-01-01T11:00:00+08:00"
      },
      "can_print": true
    }

    错误

    • 404 not_found — 条目不存在、已下架或无权查看
  • GET/template-shares/:shareId/releasestemplate:read

    列出条目的发布记录

    企业侧只公开发布台账,不公开作者的草稿版本。用于追溯和历史补打。

    参数与响应

    参数

    名称位置类型说明
    shareId*路径string条目 ID(share_id)
    pageQueryinteger页码,从 1 开始,默认 1
    page_sizeQueryinteger每页条数,默认 20,最大 100

    响应 · 分页列表<ReleaseItem>

    {
      "items": [
        {
          "id": "1938475610293850112",
          "version_no": 3,
          "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
          "name": "发货标签 100×150",
          "width": 100,
          "height": 150,
          "size_unit": "mm",
          "source": 1,
          "released_at": "2025-01-01T10:00:00+08:00",
          "superseded_at": null,
          "is_current": true
        },
        {
          "id": "1938475610293849001",
          "version_no": 2,
          "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
          "name": "发货标签 100×150",
          "width": 100,
          "height": 150,
          "size_unit": "mm",
          "source": 2,
          "released_at": "2024-12-01T09:30:00+08:00",
          "superseded_at": "2025-01-01T10:00:00+08:00",
          "is_current": false
        }
      ],
      "total": 2,
      "page": 1,
      "page_size": 20
    }

    错误

    • 404 not_found — 条目不存在或无权查看
  • GET/template-shares/:shareId/contenttemplate:read

    获取模板内容

    不传 release_id 时返回当前生效的内容;传入时返回该发布记录的内容(历史补打)。

    参数与响应

    参数

    名称位置类型说明
    shareId*路径string条目 ID(share_id)
    release_idQuerystring发布记录 ID,可选。必须是正整数,非法值直接返回 400,不会当作不传处理。

    响应 · ContentResponse

    {
      "version_no": 3,
      "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "width": 100,
      "height": 150,
      "size_unit": "mm",
      "title": "发货标签 100×150",
      "content": {
        "...": "模板设计内容(JSON 对象)"
      }
    }

    错误

    • 400 invalid_parameter — release_id 不是正整数
    • 404 not_found — 条目或发布记录不存在
    • 409 share_not_listed — 条目当前没有上架
    • 409 content_hash_mismatch — 内容指纹校验失败,请求被拒绝
    • 409 template_content_missing — 模板内容缺失
  • GET/template-groupstemplate:read

    列出模板分组

    参数与响应

    响应 · { groups: GroupItem[] }

    {
      "groups": [
        {
          "id": "1938475610293840001",
          "name": "物流标签",
          "description": "仓库发货使用",
          "sort_order": 0
        }
      ]
    }
  • GET/template-groups/:groupId/templatestemplate:read

    列出分组下的模板条目

    参数与响应

    参数

    名称位置类型说明
    groupId*路径string分组 ID
    nameQuerystring按模板名称筛选
    tagsQuerystring[]按标签筛选,可以重复传:tags=a&tags=b
    statusQueryinteger已废弃只为兼容旧集成保留:不传或传 1 时正常返回,传其他值返回 400。include_inactive 会被忽略。
    pageQueryinteger页码,从 1 开始,默认 1
    page_sizeQueryinteger每页条数,默认 20,最大 100

    响应 · 分页列表<TemplateItem>

    {
      "items": [
        {
          "share_id": "1938475610293847552",
          "group_id": "1938475610293840001",
          "share_code": "S-7K2M9Q",
          "release_id": "1938475610293850112",
          "version_no": 3,
          "name": "发货标签 100×150",
          "description": null,
          "width": 100,
          "height": 150,
          "size_unit": "mm",
          "source": 1,
          "released_at": "2025-01-01T10:00:00+08:00",
          "thumbnail": {
            "url": "https://<oss-domain>/<signed-path>",
            "expires_at": "2025-01-01T11:00:00+08:00"
          },
          "can_print": true
        }
      ],
      "total": 1,
      "page": 1,
      "page_size": 20
    }

    错误

    • 400 invalid_parameter — status 传了 1 以外的值
    • 403 forbidden — 无权访问该分组
    • 404 not_found — 分组不存在

模板接口错误码

400invalid_parameter参数不合法,修正后再调用
403forbidden无权访问该分组或条目(不区分具体原因)
404not_found资源不存在、不属于当前企业,或无权查看
409share_not_listed条目存在,但当前没有在分组中上架。请联系分组管理员
409content_hash_mismatch内容指纹不一致,平台已拒绝下发。请勿重试,联系平台支持
409template_content_missing模板内容缺失,需要模板作者重新保存
410endpoint_removed调用了已下线的旧接口,响应里有迁移指引

数据结构

TemplateItem

企业模板条目。所有展示字段都来自当前生效的发布记录快照,与作者个人库里模板的当前状态无关。

字段类型说明
share_idstring条目 ID,企业侧的主键
group_idstring所属分组 ID
share_codestring槽位编码,格式 S-XXXXXX。条目生命周期内不变
release_idstring当前生效的发布记录 ID。它变了,就说明生效版本变了(包括回滚)
version_nointeger生效版本号
namestring模板名称(发布时快照)
descriptionstring | null模板描述(发布时快照)
widthnumber标签宽度,单位见 size_unit
heightnumber标签高度,单位见 size_unit
size_unitstring尺寸单位:mm / cm / in / px
sourceinteger生效来源:1 审核通过,2 免审直发,3 管理员回滚
released_atstring生效时间(RFC 3339)
thumbnailFileURL | null封面图临时地址;封面还在异步生成时为 null
can_printboolean当前凭证能否用这个条目提交打印

ReleaseItem

条目的一条发布记录。发布记录只增不改;回滚会新增一条指向旧版本的记录,不会复用旧记录。

字段类型说明
idstring发布记录 ID,可作为 content 接口的 release_id
version_nointeger版本号
content_hashstring内容指纹(SHA-256,64 位十六进制)
namestring模板名称快照
widthnumber标签宽度快照
heightnumber标签高度快照
size_unitstring尺寸单位快照
sourceinteger1 审核通过,2 免审直发,3 管理员回滚
released_atstring生效时间
superseded_atstring | null被替代或下架的时间;null 表示当前生效
is_currentboolean是否为当前生效记录

ContentResponse

某条发布记录对应的模板内容。

字段类型说明
version_nointeger版本号
content_hashstring内容指纹,可作为缓存键
widthnumber标签宽度
heightnumber标签高度
size_unitstring尺寸单位
titlestring打印标题
contentobject模板设计内容

GroupItem

字段类型说明
idstring分组 ID
namestring分组名称
descriptionstring | null分组描述
sort_orderinteger排序权重

FileURL

带签名的临时地址。请在 expires_at 之前重新拉取,不要等到图片加载失败再处理。

字段类型说明
urlstring临时访问地址
expires_atstring地址失效时间(服务端签名的真实过期时间)

分页列表

分页列表接口的统一结构。模板分组列表({ groups })和可打印的打印机列表(for-print)不分页,结构单独说明。

字段类型说明
itemsarray当前页数据
totalinteger总条数
pageinteger当前页码
page_sizeinteger每页条数(服务端修正后的实际值)

打印机

查询打印机及其运行状态。提交打印任务前,可以用 for-print 拿到已绑定且已启用的打印机,以及它们的在线状态。

  • •提交打印任务使用打印机的 code(printer_code),不是 id。for-print 不返回 code,请用 GET /printers 或 /printers/:id 获取;code 为空的打印机不能通过 OpenAPI 提交任务。
  • •GET /printers 默认只返回 status=active 且 bind_status=bound 的打印机。要查看全部,请传 include_unusable=true。
  • •GET /printers/:id 不按状态过滤,可能返回已禁用或已解绑的打印机。使用前请检查 status 和 bind_status。
  • •online 由服务端根据 last_reported_at 计算;runtime_status 是打印机最后一次上报的值。打印机掉线后,runtime_status 可能仍停留在 READY,判断是否可用时请同时看这两个字段。
  • •打印机接口中没有值的字段会被省略,不会返回 null,请按字段可能不存在处理。
  • GET/printers/for-printprinter:read

    列出可用于打印的打印机(按终端分组)

    只返回已绑定且已启用的打印机,附带在线状态。不分页。

    参数与响应

    响应 · ListForPrintResponse

    {
      "groups": [
        {
          "terminal_id": "1938475610293870001",
          "terminal_name": "仓库前台电脑",
          "terminal_code": "<terminal-code>",
          "terminal_online": true,
          "printers": [
            {
              "id": "1938475610293860001",
              "name": "仓库 1 号机",
              "device_key": "<device-key>",
              "conn_type": "USB_DIRECT",
              "model_name": "ZD421",
              "default_dpi": 203,
              "default_lang": "ZPL",
              "print_width_mm": 104,
              "print_height_mm": 150,
              "runtime_status": "READY",
              "online": true,
              "last_reported_at": "2025-01-01T10:00:00+08:00"
            }
          ]
        }
      ],
      "total_count": 1,
      "online_count": 1
    }
  • GET/printersprinter:read

    分页查询打印机列表

    默认只返回已启用且已绑定的打印机。

    参数与响应

    参数

    名称位置类型说明
    nameQuerystring按名称筛选
    device_keyQuerystring按设备标识筛选
    tagQuerystring按标签筛选(单个)
    conn_typeQuerystring按连接类型筛选:USB_DIRECT / WINDOWS_SPOOLER / CUPS / NETWORK
    include_unusableQuerystring传 true(小写)时返回所有状态的打印机,其他值都按不传处理
    statusQueryinteger业务状态:1 启用,2 禁用。只在 include_unusable=true 时生效,否则会被忽略
    bind_statusQueryinteger绑定状态:0 已发现,1 已绑定,2 已解绑。只在 include_unusable=true 时生效,否则会被忽略
    pageQueryinteger页码,从 1 开始,默认 1
    page_sizeQueryinteger每页条数,默认 20,最大 100

    响应 · 分页列表<Printer>

    {
      "items": [
        {
          "id": "1938475610293860001",
          "code": "<printer-code>",
          "name": "仓库 1 号机",
          "device_key": "<device-key>",
          "conn_type": "USB_DIRECT",
          "terminal_id": "1938475610293870001",
          "group_id": "1938475610293880001",
          "status": "active",
          "bind_status": "bound",
          "model_name": "ZD421",
          "manufacturer": "Zebra",
          "default_dpi": 203,
          "default_lang": "ZPL",
          "print_width_mm": 104,
          "print_height_mm": 150,
          "runtime_status": "READY",
          "online": true,
          "last_reported_at": "2025-01-01T10:00:00+08:00",
          "capabilities": {
            "max_width_mm": 104,
            "supported_dpi": [203, 300],
            "supported_langs": ["ZPL", "EPL"],
            "has_cutter": true
          },
          "tags": ["仓库A"],
          "firmware_version": "V84.20.21Z",
          "bound_at": "2024-12-01T09:00:00+08:00",
          "updated_at": "2025-01-01T10:00:00+08:00",
          "created_at": "2024-12-01T09:00:00+08:00"
        }
      ],
      "total": 1,
      "page": 1,
      "page_size": 20
    }

    错误

    • 400 invalid_parameter — status 或 bind_status 不是整数
  • GET/printers/:idprinter:read

    查询打印机详情

    不按状态过滤,可能返回已禁用或已解绑的打印机。

    参数与响应

    参数

    名称位置类型说明
    id*路径string打印机 ID

    响应 · Printer

    {
      "id": "1938475610293860001",
      "code": "<printer-code>",
      "name": "仓库 1 号机",
      "device_key": "<device-key>",
      "conn_type": "USB_DIRECT",
      "terminal_id": "1938475610293870001",
      "group_id": "1938475610293880001",
      "status": "active",
      "bind_status": "bound",
      "model_name": "ZD421",
      "manufacturer": "Zebra",
      "default_dpi": 203,
      "default_lang": "ZPL",
      "print_width_mm": 104,
      "print_height_mm": 150,
      "runtime_status": "READY",
      "online": true,
      "last_reported_at": "2025-01-01T10:00:00+08:00",
      "capabilities": {
        "max_width_mm": 104,
        "supported_dpi": [203, 300],
        "supported_langs": ["ZPL", "EPL"],
        "has_cutter": true
      },
      "tags": ["仓库A"],
      "firmware_version": "V84.20.21Z",
      "bound_at": "2024-12-01T09:00:00+08:00",
      "updated_at": "2025-01-01T10:00:00+08:00",
      "created_at": "2024-12-01T09:00:00+08:00"
    }

    错误

    • 400 invalid_parameter — id 不是正整数
    • 404 not_found — 打印机不存在或不属于当前企业

打印机接口错误码

400invalid_parameter参数不合法,修正后再调用
404not_found打印机不存在或不属于当前企业
500internal_error服务端异常,可以退避重试

数据结构

Printer

打印机详情。标注「可省略」的字段在没有值时不出现在响应里(不会返回 null),请按字段可能不存在处理。

字段类型说明
idstring打印机 ID,用于查询详情和筛选任务
codestring打印机编码,提交打印任务时作为 printer_code 使用。可能为空字符串:没有编码的打印机不能通过 OpenAPI 提交任务
namestring打印机名称
device_keystring设备唯一标识
conn_typestring连接类型:USB_DIRECT / WINDOWS_SPOOLER / CUPS / NETWORK
terminal_idstring所属终端 ID
group_idstring所属打印机分组 ID。可省略:未分组时不返回
statusstring业务状态:active 启用,disabled 禁用
bind_statusstring绑定状态:discovered 已发现,bound 已绑定,unbound 已解绑
model_namestring型号。可省略
manufacturerstring制造商。可省略
firmware_versionstring固件版本。可省略
default_dpiinteger默认分辨率(DPI),未配置时为 203
default_langstring默认指令语言,如 TSPL / ZPL。可省略
print_width_mmnumber可打印宽度(毫米),未配置时为 0
print_height_mmnumber可打印高度(毫米),未配置时为 0
runtime_statusstring打印机最近一次上报的运行状态,如 READY / ERROR / OFFLINE / BUSY。可省略:从未上报时不返回
status_messagestring运行状态的说明文字。可省略
onlineboolean服务端计算:last_reported_at 在最近 60 秒内为 true,否则为 false
last_reported_atstring最近一次上报状态的时间。可省略:从未上报时不返回
capabilitiesPrinterCapabilities打印机能力。可省略
tagsstring[]标签。可省略:没有标签时不返回
bound_atstring绑定时间。可省略
unbound_atstring解绑时间。可省略
created_atstring创建时间
updated_atstring更新时间

PrinterCapabilities

以下字段都可省略:未上报、值为 0、false 或空数组时不返回。

字段类型说明
max_width_mminteger最大打印宽度(毫米)
max_height_mminteger最大打印高度(毫米)
supported_dpiinteger[]支持的分辨率
supported_langsstring[]支持的指令语言,如 TSPL、ZPL、EPL、CPCL、ESC/POS
has_cutterboolean是否有切刀
has_peelerboolean是否有剥离器
color_supportboolean是否支持彩色

ListForPrintResponse

按终端分组的可打印打印机列表,不分页。

字段类型说明
groupsarray按终端分组的列表,每项结构见下面的 groups[] 字段
groups[].terminal_idstring终端 ID
groups[].terminal_namestring终端名称
groups[].terminal_codestring终端编码
groups[].terminal_onlineboolean终端在线状态
groups[].printersarray该终端下的打印机,字段见 PrinterForPrintItem
total_countinteger打印机总数
online_countinteger其中在线的打印机数

PrinterForPrintItem

Printer 的精简版,字段含义与 Printer 相同。不含 code、status、bind_status、capabilities 等字段。

字段类型说明
idstring打印机 ID
namestring打印机名称
device_keystring设备唯一标识
conn_typestring连接类型
model_namestring型号。可省略
default_dpiinteger默认分辨率(DPI)
default_langstring默认指令语言。可省略
print_width_mmnumber可打印宽度(毫米)
print_height_mmnumber可打印高度(毫米)
runtime_statusstring最近一次上报的运行状态。可省略
onlineboolean根据 last_reported_at 计算的在线状态
last_reported_atstring最近一次上报状态的时间。可省略

分页列表

分页列表接口的统一结构。模板分组列表({ groups })和可打印的打印机列表(for-print)不分页,结构单独说明。

字段类型说明
itemsarray当前页数据
totalinteger总条数
pageinteger当前页码
page_sizeinteger每页条数(服务端修正后的实际值)

存储

上传模板会用到的图片、字体等文件。流程分三步:申请上传 → 直传 → 确认。

  • GET/storage/usagestorage:read

    查询存储用量

  • POST/storage/uploadsstorage:write计配额

    申请上传,获取直传地址

  • POST/storage/uploads/:id/confirmstorage:write计配额

    确认上传完成

  • GET/storage/filesstorage:read

    分页查询文件列表

  • GET/storage/files/:idstorage:read

    查询文件详情

  • GET/storage/files/:id/urlstorage:read

    获取临时下载地址

  • DELETE/storage/files/:idstorage:write计配额

    删除文件

已下线接口

旧版模板接口按模板 ID 寻址,已经下线。调用时返回 410 Gone(code 为 endpoint_removed)和迁移指引。新接口按条目寻址,迁移时请注意:

  • • 主键从 template_id 换成 share_id。也可以直接用 share_code 定位条目。
  • • 「版本列表」换成「发布记录」:只包含在企业侧正式生效过的版本,不含作者的草稿。
  • • 取历史版本内容时,参数从 versionId 换成 release_id。
  • • 列表接口的 status 筛选已废弃:只返回已上架的条目。传 1 仍然兼容,传其他值返回 400。
旧接口替代接口
GET /templates/:idGET /template-shares/:shareId
GET /templates/:id/versionsGET /template-shares/:shareId/releases
GET /templates/:id/versions/:versionIdGET /template-shares/:shareId/content?release_id=

准备好开始对接了吗?

企业版提供沙箱环境、更高的 QPM 和专属技术支持,帮你更快完成与 ERP / WMS / MES 的集成。