Developer · Open API

开放接口文档

面向店铺开发者与自动化 agent 的开放接口。一次 HTTP 调用即可把商品上架到你的店铺—— 无需登录后台、无需人工点选。下面是接通所需的全部内容:鉴权、字段、示例与错误码。

Base URL https://api.kjlong.com
鉴权 Authorization: Bearer sk_ / ak_
契约版本 v1.2 · 2026-07-25

01 — Overview

概览

🤖 接入方是 AI Agent? 给它这份纯 Markdown 版全量契约(含错误码重试策略与自检清单),一个链接即可完成对接: https://kjlong.com/developers/agent.md

开放接口面向店铺开发者与自动化 agent——适合用脚本批量上品、对接自有 ERP/选品系统、驱动采集工具,或让 agent 自动完成商品录入。 单店脚本用店铺级 sk_,需要在多家店之间切换的工具用账号级 ak_(见 鉴权与 Token)。所有请求走统一的 Base URL:

Base URL https://api.kjlong.com
协议 HTTPS。写接口 POST + multipart/form-data,读接口 GET + query 参数
鉴权方式 请求头 Authorization: Bearer <token> —— 店铺级 sk_ 或账号级 ak_

02 — Authentication

鉴权与 Token

接口以 API Token 鉴权,两种令牌共用同一个请求头

HTTP Header
Authorization: Bearer <sk_ ak_>

两者都在商户后台「设置 → 开发者」页面获得,区别在于 作用范围店铺怎么指定

sk_ 店铺级 ak_ 账号级
作用范围 一店一枚,绑死单个店铺 覆盖账号名下全部店铺
怎么拿 「设置 → 开发者 → 店铺 API Token」手动生成 「设置 → 开发者 → Chrome 采集插件」授权插件时自动签发
数量 每店一枚(重新生成即作废旧的) 可有多枚(多设备各一枚),可逐枚单独吊销
店铺由谁定 Token 本身 请求头 X-Store-Id
X-Store-Id 不需要,也不应该带(带了会被忽略) 调店铺维度端点时必须带
典型用途 服务器上的定时脚本、自有 ERP 对接单店 Chrome 采集插件、需要在多店间切换的工具

已在用 sk_ 的接入方无需任何改动。 sk_ 的行为与此前完全一致:店铺归属由 Token 决定,请求里的 storeId 字段被忽略,不需要也不要带 X-Store-Id

ak_ 的 X-Store-Id 规则

账号级 Token 覆盖多家店,所以每次调用都要说明「打哪家店」。值为店铺的数字 ID,从 店铺列表 获取:

HTTP Headers · ak_
Authorization: Bearer ak_xxx
X-Store-Id: 3
  • 后端校验该店铺是否属于该 Token 所属账号,不通过即拒绝—— ak_ 拿不到别人的店。
  • X-Store-Id 缺失或不是数字4100(HTTP 400)。Token 本身没问题,纯参数问题。
  • X-Store-Id 指向的店铺不存在,或存在但不属于该账号4404(HTTP 404)。 两种情况故意不区分,避免接口被拿来探测某个 storeId 是否存在。
  • 唯一不带 X-Store-Id 的端点是 /openapi/store/list——它天然没有店铺维度。

鉴权失败统一返回:Token 无效或缺失 → code = 4001(HTTP 401);Token 已停用或已被吊销 → code = 4002(HTTP 403)。详见 错误码

03 — Response Envelope

响应信封

所有响应都是统一信封 { code, msg, data, success }

响应信封
{
  "code": 0,
  "msg": "success",
  "data": { },
  "success": true
}
字段类型说明
successbool成功与否的权威判据,成功为 true
codeint业务码,成功为 0;失败见错误码表
msgstring提示信息,失败时说明原因
dataobject业务数据,随接口而定

code 与 HTTP 状态码均语义化、均可靠。每个业务码都对应 一个明确的 HTTP 状态(如 40014014003/40044294404404), 两个维度按需读取都行;为便于精确分支,推荐以 success 判成败、以 code 定分支。

04 — Rate Limits

限流与配额

三个互不抵扣的计数桶。窗口一律按 UTC 划分(小时桶为整点固定窗口, 日桶为 UTC 日切):

计量维度额度可否调整
小时限流 按店铺 默认 600 次 / 小时 平台后台可配,0 = 不限
账号兜底 按账号 固定 120 次 / 小时 不可配
上架日限额 按店铺 默认 200 次 / 天 平台后台可配

小时限流 — 按店铺计

  • 同一店铺下 sk_ak_ 共享该店铺的同一个桶——换令牌换不来额度。
  • ak_ 打不同店铺时,各店各有独立的小时桶 (打 3 家店约等于 3 份额度)。
  • 被拒绝的调用同样计数、且不回滚(含参数错误、图片错误、404 等业务失败), 所以别用重试硬撞。
  • 超限返回 4004(HTTP 429),退避 ≥ 60 秒后重试。

账号兜底桶 — 120 次 / 小时

账号维度、全设备共享、不可配置。只有两类请求会命中它:

  • /openapi/store/list 的正常调用—— 该端点没有店铺维度,只计这个桶,不碰任何店铺的桶。
  • 任何未通过归属校验的请求——缺 X-Store-IdX-Store-Id 非法、或指向不属于本账号的店铺。这类请求落不到任何店铺桶上, 若不计数就等于绕过限流。

不要高频轮询店铺列表。 /openapi/store/list 只吃 120 次/时 的账号桶,而这个桶被同一账号下 所有设备共享——一个设备打满,其余设备一起被拒。 请在本地缓存店铺列表,仅在用户打开店铺选择器、或刚新建店铺时重拉。

上架日限额 — 默认 200 / 店 / 天

  • 只有 /openapi/product/create 消耗, 且仅成功上架才扣;参数、图片、引用校验失败不计入。
  • 按店铺计、UTC 日切。ak_ 打不同店铺时各店各有独立日限额。
  • 达到上限返回 4003(HTTP 429), 其余端点不受影响;等次日(UTC)再上架。

05 — Endpoints

接口总览

开放接口目前提供七个端点:商品的上架、检索、查询与编辑, 外加店铺列表、分类列表与图片上传三个辅助端点。共享同一套约定:

  • 均以 Bearer Token 鉴权(见 鉴权与 Token)。
  • 请求体不带 storeId:payload 里若带 storeId 会被忽略。店铺由 sk_ 本身、或 ak_X-Store-Id 请求头决定。
  • 限流与配额:小时限流按店铺计、上架日限额按店铺计, /openapi/store/list 走账号兜底桶。详见 限流与配额
方法路径用途令牌X-Store-Id日限额
GET/openapi/store/list 名下店铺清单ak_ 不带不消耗
GET/openapi/category/list 本店分类清单sk_ / ak_ ak_ 必带不消耗
POST/openapi/media/upload 纯图片上传(不建商品)sk_ / ak_ ak_ 必带不消耗
POST/openapi/product/create 上架新商品sk_ / ak_ ak_ 必带消耗
GET/openapi/product/list 分页检索(裁剪投影)sk_ / ak_ ak_ 必带不消耗
GET/openapi/product/get 单个商品全量详情sk_ / ak_ ak_ 必带不消耗
POST/openapi/product/update 部分更新已有商品sk_ / ak_ ak_ 必带不消耗

推荐接入流程 · 采集类场景

把外站商品搬进店铺,一次 create 建成,不要绕路:

  • store/list 拿 storeId(本地缓存)。
  • category/listcategoryCode(本地缓存)。
  • media/upload 把详情长图转存,拿回 [{ key, url }]
  • 把第 ③ 步的 url 拼进 description HTML。
  • product/create 一次建品:商品图集走本次请求的 images part,详情图已在 description 里。

不要再用「create → get → update」老路径。media/upload 上线前,想把我们的图片 URL 嵌进详情只能先建品、 再查详情取 URL、再回填——比上面多两次请求,且中间存在「详情图缺失」的脏态。 现在 ③ + ⑤ 两步即可,无中间态。

06 — Store List

店铺列表

GET /openapi/store/list

返回当前账号名下的全部店铺,用于让工具端填店铺选择器、并拿到后续请求要用的 X-Store-Id。不分页(单账号店铺数天然可控)。

仅账号级 ak_ 可调,且不带 X-Store-Idsk_ 调用返回 4001, msg 为「该接口仅支持账号级 Token(ak_)」——sk_ 绑死单店, 「名下所有店」对它没有意义。

返回字段

data 是店铺数组,每项:

字段类型说明
idint店铺 ID,即后续请求 X-Store-Id 的值
namestring店铺名称
subdomainstring买家端子域名
currencystring店铺币种
statusint店铺状态,1(启用)/ 0(停用)

调用配额

只消耗账号兜底桶(120 次 / 小时、全设备共享),不碰任何店铺的小时额度, 也不消耗上架日限额。请本地缓存,切勿高频轮询——详见 限流与配额

示例 · curl

cURL · 店铺列表
curl -G https://api.kjlong.com/openapi/store/list \
  -H "Authorization: Bearer ak_xxx"

响应示例

200 · 店铺列表
{
  "code": 0,
  "msg": "success",
  "data": [
    { "id": 3, "name": "GoldCoast Mart", "subdomain": "goldcoast", "currency": "GHS", "status": 1 },
    { "id": 7, "name": "Lagos Outlet",   "subdomain": "lagos",     "currency": "NGN", "status": 1 }
  ],
  "success": true
}

07 — Categories

分类列表

GET /openapi/category/list

返回当前店铺的分类清单(sk_ 取令牌所属店,ak_X-Store-Id 指定店),用于在上架前拿到合法的 categoryCode两种令牌都可调。sort 升序返回,不分页。

返回字段

字段类型说明
codestring上架 / 编辑 / 检索时 categoryCode 要填的就是它(不是 id)
namestring分类名称
sortint排序值,升序
statusint分类状态,1(启用)/ 0(停用)

不按 status 过滤——下架分类同样会出现在列表里。 这与 上架接口 解析 categoryCode 的口径一致(建品时下架分类同样能被引用)。若这里滤掉,就会出现 「列表里没有、但 create 能用」的割裂。需要只展示启用分类,请在你这端按 status 筛。

示例 · curl

cURL · 分类列表(两种令牌)
# sk_(店铺级)——店铺由 Token 决定,不带 X-Store-Id
curl -G https://api.kjlong.com/openapi/category/list \
  -H "Authorization: Bearer sk_xxx"

# ak_(账号级)——必须指明打哪家店
curl -G https://api.kjlong.com/openapi/category/list \
  -H "Authorization: Bearer ak_xxx" \
  -H "X-Store-Id: 3"

响应示例

200 · 分类列表
{
  "code": 0,
  "msg": "success",
  "data": [
    { "code": "phones",  "name": "Phones",      "sort": 1, "status": 1 },
    { "code": "audio",   "name": "Audio",       "sort": 2, "status": 1 },
    { "code": "clearance", "name": "Clearance", "sort": 9, "status": 0 }
  ],
  "success": true
}

08 — Media Upload

图片上传

POST /openapi/media/upload

multipart/form-data,文件字段名固定 images(可重复)。 只把图片存进店铺素材库并返回地址,不创建商品。两种令牌都可调。

它是「详情图先转存、再一次建品」的关键一步。 先用本接口把外站详情长图转存到我们的存储、拿到 url,把这些 url 拼进 description HTML,然后一次 product/create 建成商品—— 比旧的「create → get → update」少两次请求,且不存在中间脏态。

请求

part数量说明
images 1 ~ 100 文件 part,字段名固定为 images

校验口径与 上架接口 完全一致:单图 ≤ 10MB、类型限 jpeg / png / webp / gif、单请求总大小 ≤ 100MB、 最多 100 张。任一张校验失败 → 整批失败 并指明第几张(4200)。

返回字段

data 是数组,顺序与入参 part 顺序一致

字段类型说明
keystring存储键,可直接填进 create / update 的图片引用位
urlstring公网可读地址,可直接嵌进 description HTML

调用配额

不消耗上架日限额——日限额的语义是「上架了多少个商品」,传图不是上架, 否则传 60 张详情图就把当天的上架额度烧光了。 但消耗店铺小时限流(见 限流与配额)。 同店同图按内容去重(秒传),重复上传返回同一 key / url, 不产生冗余对象。

示例 · curl

ak_ 把两张详情图转存到店铺 3 的素材库:

cURL · 图片上传
curl -X POST https://api.kjlong.com/openapi/media/upload \
  -H "Authorization: Bearer ak_xxx" \
  -H "X-Store-Id: 3" \
  -F 'images=@detail_01.jpg' -F 'images=@detail_02.jpg'

响应示例

200 · 图片上传
{
  "code": 0,
  "msg": "success",
  "data": [
    { "key": "store/3/9c1e2f.jpg", "url": "https://res.kjlong.com/store/3/9c1e2f.jpg" },
    { "key": "store/3/4b7a80.jpg", "url": "https://res.kjlong.com/store/3/4b7a80.jpg" }
  ],
  "success": true
}

示例 · 接着一次建品

把上一步返回的 url 嵌进 description,商品图集走本次请求的 images part,一次调用完成:

cURL · 转存后建品
curl -X POST https://api.kjlong.com/openapi/product/create \
  -H "Authorization: Bearer ak_xxx" \
  -H "X-Store-Id: 3" \
  -F 'payload={"title":"Collected Phone","categoryCode":"phones","price":199.00,"stock":50,"description":"<p><img src=\"https://res.kjlong.com/store/3/9c1e2f.jpg\"></p>"}' \
  -F 'images=@main_01.jpg'

09 — Create Product

上架商品

POST /openapi/product/create

一次 multipart/form-data 请求即完成商品创建。请求体由两种 part 组成:

part数量说明
payload 1 文本 part,商品信息 JSON,≤ 1MB
images 0 ~ 100 文件 part,商品/规格图片

图片规则

  • 顺序即图集顺序images 的排列顺序就是商品图集顺序,第一张为主图。
  • 单图 ≤ 10MB;类型限 jpeg / png / webp / gif
  • 单次请求所有 part 总大小 ≤ 100MB
  • 任一图片校验失败,整单失败并指明第几张,不会产生半成品商品。

payload 通用字段

字段类型必填说明
titlestring商品标题,≤ 255 字
substring副标题
descriptionstring商品详情,支持 HTML;内嵌图片 URL 建议先走 图片上传 转存
categoryCodestring按店内分类 code 解析(取自 分类列表);填写但不存在则整单报错
aiShortTitlestringAI 短标题
aiPromptstringAI 提示词
statusint商品状态,默认 1(上架)

简单模式 — 单一规格

不传 skus 即为简单模式,系统据下列字段生成单个 Standard SKU:

字段类型必填说明
pricenumber售价,必须 > 0
origPricenumber原价(划线价)
stockint库存

高级模式 — 多规格 SKU

skus 非空即进入高级模式,由 skuGroups[] 定义规格维度、skus[] 定义每个规格组合的绝对价与独立库存。

skuGroups[] — 每项定义一个规格维度:

字段类型说明
namestring规格组名称,如 ColorStorage
optsstring[]该规格组的可选值,如 ["Black","White"]
imageEnabledbool是否为该规格组启用规格图
optImagesobject选项值 → 图片文件名的映射,值须为 images 中某个 part 的文件名

skus[] — 每项定义一个规格组合:

字段类型说明
specstring规格组合串,各组选项以  /  连接,如 Black / 128GB
skuCodestringSKU 编码,缺省取 spec
pricenumber该 SKU 售价(绝对价)
origPricenumber该 SKU 原价
stockint该 SKU 库存
imagestring该 SKU 图片文件名,须为 images 中某个 part 的文件名
statusintSKU 状态,默认 1status ≠ 1 的 SKU 不参与最低价 / 总库存聚合

图片靠文件名映射。skus[].imageskuGroups[].optImages 的值,都填 images 里某个文件 part 的文件名,服务端据此关联; 只要引用到不存在的文件名,整单报错

成功返回

成功时 data 返回新建商品的信息:

字段说明
id商品 ID
title商品标题
status商品状态
url买家端商品页地址

调用配额

默认 200 单 / 店 / 天(按店铺计、UTC 日切,可联系平台调整)。 只有成功上架才消耗配额;参数校验失败、图片校验失败等不计入。 达到上限返回 code = 4003(HTTP 429)。 本接口同时消耗店铺小时限流,详见 限流与配额

示例 · 简单模式 curl

单一规格,三张商品图,第一张 img_red.png 为主图:

cURL · 简单模式
curl -X POST https://api.kjlong.com/openapi/product/create \
  -H "Authorization: Bearer sk_xxx" \
  -F 'payload={"title":"Open API Test Phone","sub":"via openapi","categoryCode":"phones","price":199.00,"origPrice":299.00,"stock":50,"description":"<p>Hello <b>world</b></p>"}' \
  -F 'images=@img_red.png' -F 'images=@img_green.png' -F 'images=@img_blue.png'

示例 · 高级模式 curl

两个规格维度(Color × Storage)共四个 SKU,规格图与 SKU 图用文件名引用 images 里上传的图片:

cURL · 高级模式
curl -X POST https://api.kjlong.com/openapi/product/create \
  -H "Authorization: Bearer sk_xxx" \
  -F 'payload={"title":"Advanced Phone","categoryCode":"phones","status":1,"skuGroups":[{"name":"Color","opts":["Black","White"],"imageEnabled":true,"optImages":{"Black":"img_black.png","White":"img_white.png"}},{"name":"Storage","opts":["128GB","256GB"],"imageEnabled":false}],"skus":[{"spec":"Black / 128GB","skuCode":"BLK-128","price":300,"origPrice":350,"stock":10,"image":"img_black.png"},{"spec":"Black / 256GB","skuCode":"BLK-256","price":350,"stock":8,"image":"img_black.png"},{"spec":"White / 128GB","skuCode":"WHT-128","price":320,"stock":5,"image":"img_white.png"},{"spec":"White / 256GB","skuCode":"WHT-256","price":370,"stock":0,"status":0,"image":"img_white.png"}]}' \
  -F 'images=@img_black.png' -F 'images=@img_white.png'

示例 · Python requests

与上面的简单模式等价,注意最后按 success / code 分支:

Python · requests
import requests

url = "https://api.kjlong.com/openapi/product/create"
headers = {"Authorization": "Bearer sk_xxx"}

# payload:一个 JSON 文本 part,内容与简单模式 curl 完全一致
payload = (
    '{"title":"Open API Test Phone","sub":"via openapi",'
    '"categoryCode":"phones","price":199.00,"origPrice":299.00,'
    '"stock":50,"description":"<p>Hello <b>world</b></p>"}'
)

# images:文件 part,顺序即商品图集顺序,第一张为主图
files = [
    ("images", ("img_red.png",   open("img_red.png",   "rb"), "image/png")),
    ("images", ("img_green.png", open("img_green.png", "rb"), "image/png")),
    ("images", ("img_blue.png",  open("img_blue.png",  "rb"), "image/png")),
]

resp = requests.post(url, headers=headers, data={"payload": payload}, files=files)
result = resp.json()

# 按 success 判断成败,按 code 精确分支(HTTP 状态码同样语义化、可一并参考)
if result["success"]:
    print("上架成功:", result["data"]["url"])
else:
    print("上架失败:", result["code"], result["msg"])

成功返回示例

200 · 成功
{"code":0,"msg":"success","data":{"id":389,"title":"Open API Test Phone","status":1,"url":"https://yourstore.kjlong.com/product/389"},"success":true}

10 — List Products

商品列表

GET /openapi/product/list

分页检索本店商品,用于对账、增量同步,或在编辑前先定位商品 ID。返回的是 裁剪投影——不含 description 等重字段;需要全量请用 商品详情

Query 参数

参数类型必填说明
pageint页码,从 1 起,默认 1
sizeint每页条数,默认 20,上限 100(超限自动收敛到 100)
statusint按状态过滤,0(下架)或 1(上架)
categoryCodestring按分类 code 过滤
keywordstring按标题模糊匹配

返回结构

字段类型说明
listarray当前页商品投影,元素字段见下表
pageint当前页码
sizeint每页条数(收敛后的实际值)
totalint符合条件的总条数
totalPagesint总页数

list[] — 单个商品投影(不含 description):

字段类型说明
idint商品 ID
titlestring标题
substring副标题
pricenumber售价(多规格为最低价聚合)
origPricenumber原价(划线价)
stockint库存(多规格为总和聚合)
statusint状态,0 / 1
apiLockedintAPI 编辑锁,1=锁定(编辑接口会拒绝)/ 0=开放
categoryCodestring分类 code
mainImagestring主图 URL(可直接展示)
createTimestring创建时间,yyyy-MM-dd HH:mm:ss
modifyTimestring修改时间,yyyy-MM-dd HH:mm:ss

示例 · curl

取第 1 页、每页 20 条、仅上架、标题含 phone 的商品:

cURL · 列表
curl -G https://api.kjlong.com/openapi/product/list \
  -H "Authorization: Bearer sk_xxx" \
  -d page=1 -d size=20 -d status=1 -d keyword=phone

响应示例

200 · 列表
{
  "code": 0,
  "msg": "success",
  "data": {
    "list": [
      {
        "id": 412,
        "title": "Advanced Phone",
        "sub": "",
        "price": 300.00,
        "origPrice": 350.00,
        "stock": 23,
        "status": 1,
        "apiLocked": 0,
        "categoryCode": "phones",
        "mainImage": "https://res.kjlong.com/upload/2026/06/8f3a1c.png",
        "createTime": "2026-06-20 10:31:55",
        "modifyTime": "2026-06-21 08:04:12"
      },
      {
        "id": 389,
        "title": "Open API Test Phone",
        "sub": "via openapi",
        "price": 199.00,
        "origPrice": 299.00,
        "stock": 50,
        "status": 1,
        "apiLocked": 0,
        "categoryCode": "phones",
        "mainImage": "https://res.kjlong.com/upload/2026/06/5e1f0a.png",
        "createTime": "2026-06-20 09:12:03",
        "modifyTime": "2026-06-20 09:12:03"
      }
    ],
    "page": 1,
    "size": 20,
    "total": 2,
    "totalPages": 1
  },
  "success": true
}

11 — Get Product

商品详情

GET /openapi/product/get?id=

返回单个商品的全量详情,含图片、规格与 SKU 的完整结构。 商品不存在、或不属于本店 → 4404(两种情况不区分)。

Query 参数

参数类型必填说明
idint商品 ID

返回字段

顶层为商品常规字段,外加图片与规格结构:

字段类型说明
id / title / sub / description商品常规字段(详情含 HTML)
categoryCodestring分类 code
price / origPrice / stock / status聚合价、原价、总库存与状态
apiLockedintAPI 编辑锁,1=锁定 / 0=开放;编辑前先看这个值
aiShortTitle / aiPromptstringAI 短标题与提示词
urlstring买家端商品页地址
mainImageobject|null{ key, url },无主图为 null
imagesarray图集,元素为 { key, url }
skuGroupsarray规格维度定义;其中 optImages 的值为图片 URL
skusarraySKU 列表,元素字段见下表

skus[] — 单个 SKU:

字段类型说明
idintSKU ID
specstring规格组合串,如 Black / 128GB
skuCodestringSKU 编码
price / origPricenumber该 SKU 售价 / 原价
stockint该 SKU 库存
statusint该 SKU 状态
imageobject|null{ key, url },无图为 null

key 供引用,url 供展示。图片对象里的 key 是稳定的存储键, 拿去编辑接口images / optImages / image 里即可复用已有图、无需重新上传; url 则是可直接放进页面的展示地址。

示例 · curl

cURL · 详情
curl -G https://api.kjlong.com/openapi/product/get \
  -H "Authorization: Bearer sk_xxx" \
  -d id=412

响应示例

200 · 详情
{
  "code": 0,
  "msg": "success",
  "data": {
    "id": 412,
    "title": "Advanced Phone",
    "sub": "",
    "description": "<p>Hello <b>world</b></p>",
    "categoryCode": "phones",
    "price": 300.00,
    "origPrice": 350.00,
    "stock": 23,
    "status": 1,
    "apiLocked": 0,
    "aiShortTitle": "",
    "aiPrompt": "",
    "url": "https://yourstore.kjlong.com/product/412",
    "mainImage": {
      "key": "upload/2026/06/8f3a1c.png",
      "url": "https://res.kjlong.com/upload/2026/06/8f3a1c.png"
    },
    "images": [
      { "key": "upload/2026/06/8f3a1c.png", "url": "https://res.kjlong.com/upload/2026/06/8f3a1c.png" },
      { "key": "upload/2026/06/7d2e9b.png", "url": "https://res.kjlong.com/upload/2026/06/7d2e9b.png" }
    ],
    "skuGroups": [
      {
        "name": "Color",
        "opts": ["Black", "White"],
        "imageEnabled": true,
        "optImages": {
          "Black": "https://res.kjlong.com/upload/2026/06/8f3a1c.png",
          "White": "https://res.kjlong.com/upload/2026/06/7d2e9b.png"
        }
      }
    ],
    "skus": [
      {
        "id": 4101,
        "spec": "Black / 128GB",
        "skuCode": "BLK-128",
        "price": 300.00,
        "origPrice": 350.00,
        "stock": 10,
        "status": 1,
        "image": {
          "key": "upload/2026/06/8f3a1c.png",
          "url": "https://res.kjlong.com/upload/2026/06/8f3a1c.png"
        }
      }
    ]
  },
  "success": true
}

12 — Update Product

编辑商品

POST /openapi/product/update

请求形态与上架接口一致 (multipart/form-datapayload + 可选 images),但 payload.id 必填,且语义为 部分更新。商品不存在 / 不属本店 → 4404。本接口 不消耗上架日限额。

payload 字段

字段类型必填说明
idint目标商品 ID
其余字段同上架接口;只有传入的字段被更新,未出现的保持原样

更新语义

  • 部分更新:只改 payload 里出现的字段,其余原样保留。
  • 整体替换:images / skus / skuGroups 一旦传入,即用新值整体替换旧值;不传则保持原样。 images空数组即清空图集。
  • 图片引用可混用:图片位(images / optImages / SKU 的 image)既可填现有图的 key (来自商品详情),也可填本次上传文件的文件名
  • 移除 ≠ 删除:images[] 移除仅解除图集引用, 文件仍在店铺素材库、URL 长期有效——「图片先上传取 URL 嵌入 description,再从图集移除」是受支持的用法。
  • 商品锁定:商户可在后台锁定商品(apiLocked=1,人工创建的 默认锁定;API 创建的默认开放)。锁定商品调用本接口 → 4405/423。 列表与详情均返回 apiLocked编辑前先检查;payload 中的 apiLocked 会被忽略——锁的开关只属于商户后台。
  • 顶层 price / stock 不生效:编辑接口不吃顶层价格 / 库存, 调价 / 改库存请走 skus 的绝对价与独立库存。

示例 · 只改标题

不带 images part,图集与规格原样不动,仅更新标题:

cURL · 改标题
curl -X POST https://api.kjlong.com/openapi/product/update \
  -H "Authorization: Bearer sk_xxx" \
  -F 'payload={"id":412,"title":"Advanced Phone (2026)"}'

示例 · 混合引用重排图集

保留一张现有图(用详情返回的 key)、 再追加一张新上传文件,以新的顺序整体替换图集:

cURL · 重排图集
curl -X POST https://api.kjlong.com/openapi/product/update \
  -H "Authorization: Bearer sk_xxx" \
  -F 'payload={"id":412,"images":["upload/2026/06/8f3a1c.png","img_new.png"]}' \
  -F 'images=@img_new.png'

13 — Errors

错误码

失败时 success = false,按 code 分支处理。 HTTP 状态码同样语义化,与 code 一致、可一并参考。 下表 msg 为服务端原文,N(数量)、X(具体名称)、 f(文件名)为运行时替入的值。

codeHTTP说明与 msg 原文示例
0200 成功 —— success
4001401 Token 无效或缺失;或用 sk_ 调了仅 ak_ 可用的端点 —— 无效的 API Token
该接口仅支持账号级 Token(ak_)
4002403 Token 已停用(含 ak_ 被商户吊销) —— API Token 已停用
4003429 达到今日上架限额(仅上架接口消耗额度,失败不扣) —— 已达今日上架限额(N),可联系平台调整
4004429 调用过于频繁(店铺小时桶,或账号兜底桶 120 次/时) —— 调用过于频繁(600 次/时),请稍后重试
调用过于频繁(120 次/时),请稍后重试
4100400 参数错误(含 X-Store-Id 缺失或非数字) —— 账号级 Token 必须携带 X-Store-Id 请求头
X-Store-Id 不是合法的店铺 ID
缺少 payload 参数
payload 过大(上限 1MB)
payload 不是合法 JSON
title 必填
title 不能超过 255 字
status 只能是 0 或 1
分类 code 不存在: X
简单模式需要 price 且大于 0
第 N 个 SKU 缺少 spec
update 需要 payload.id
4200400 图片错误 —— 缺少 images 文件
图片最多 100 张
第 N 张图片为空
第 N 张图片(f)超过 10MB
第 N 张图片(f)仅支持图片格式: [gif, jpg, jpeg, webp, png]
4300400 引用错误 —— 第 N 个 SKU 引用的图片文件名不在 images 中: X
规格图 引用的图片文件名不在 images 中: X
images[N] 引用的图片既不是本次上传文件也不是现有图: X
4404404 商品不存在(含不属于本店,不区分) —— 商品不存在
X-Store-Id 指向的店铺不存在,或存在但不属于该账号 (两种情况不区分,防探测) —— 店铺不存在
4405423 商品已被商户锁定,编辑接口拒绝 —— 商品已锁定,禁止通过 API 编辑
5000500 服务端错误 —— 服务端错误

畸形请求不走这套错误码

如果请求在被路由到端点之前就被判非法——例如给 multipart 端点发了 非 multipart 的 body、Content-Type 不匹配、或用错 HTTP 动词—— 异常在 handler 映射阶段就抛出,根本没进入开放接口的错误处理。 此时返回的是平台全局信封,HTTP 状态 500

500 · 畸形请求
{"code":2,"msg":"error_system"}

分支判断前,先确认拿到的 code4xxx(或 0)。 收到 code = 2 / msg = "error_system" 时, 请当作「本地请求构造错误」处理——检查 HTTP 方法、 Content-Type、multipart 编码与字段名—— 不要当成服务端故障去重试,原样重试必然再失败。

还没有店铺?先开一家,再来接口批量上品。

免费入驻 已有账号?登录后台,在「设置 → 开发者」生成 Token。