《抖店开放平台API:落地方案、接口边界与业务踩坑 —— 2026.7.1 商品发布接口收费》(附 Python 源码)
一、2026.7.1 新规先拍死(官方口径)
抖店开放平台 2026-06-16 发《收费范围调整公告》+《技术服务费规则 V1.3》,2026-07-01 起生效:
类型 | 接口 | 抖店云内 | 抖店云外(公网/ECS/本地) | 计费 |
|---|---|---|---|---|
基础 API | /product/addV2、/product/addSchema 等 | ¥0.018 / 百次 / AppKey | ¥0.18 / 百次 / AppKey(×10) | 按实际调用量 |
基础 API | 订单/售后/商品详情等 | ¥0.018 / 百次 | ¥0.18 / 百次 | 按实际调用量 |
增值 API | 批量解密等 | ¥0.05 / 百次 | 禁止云外调用 | 按实际调用量 |
新增收费类目:
电商软件服务商 → 商品供应链
电商软件服务商 → 选品铺货-微应用
结算模型:
预充值。每月 5 号扣上月费用;余额不足 = 硬断调用(不是 429 限流);已充金额不退、不提现、不转账。
这点和拼多多一样毒:
淘宝/京东是“用后结”,抖店/拼多多是“先充钱,欠费断气”。
二、抖店 API 的“视角”和别家不同
平台 | 商品发布 | 订单真相 | 推送 |
|---|---|---|---|
淘宝 | item.add 聚石塔内 | trade.fullinfo.get | DSS 推送 |
京东 | jd.goods.create / read 模型 | jd.order.detail.get | JMQ |
拼多多 | pdd.goods.add | pdd.order.information.get | 增量轮询为主 |
抖店 | /product/addV2 / /product/addSchema | /order/orderDetail | 数据推送(订单/售后→RDS)免费 |
抖店最舒服的一点:
订单/售后数据推送是免费产品,官方明着建议你“云内调用 + 数据推送”代替轮询。
抖店最坑的一点:
商品发布以前是铺货 ERP 的“免费洼地”,2026.7.1 起填平了。店群/选品铺货/微应用 ISV 的“日发几万 SKU”模型直接变成本中心。
三、商品发布接口边界(别把 addV2 当 detail 用)
接口 | 作用 | 收费? |
|---|---|---|
/product/publishPreCheck | 发品前置校验(类目/资质/门槛) | 官方定位为前置校验,别当 addV2 发 |
/product/addSchema | Schema 草稿/结构化发品 | 收费(基础 API) |
/product/addV2 | 直接发布商品 | 收费(基础 API) |
/product/editV2 | 编辑商品 | 是否收费看当期收费列表 |
/product/listQuery | 商品列表 | 看收费列表 |
/product/detail | 商品详情 | 看收费列表 |
/spu/query | SPU 是否存在 | 批量化摊薄 |
数据推送(订单/售后) | 变更写 RDS | 免费 |
生产铁律:
免费前置校验 → 拦掉必败请求 批量查 SPU / 类目 / 属性 → 摊薄 addSchema 建草稿 → 同源商品复用 addV2 正式发 → 只发一次 listQuery 兜底 → 别逐单 detail
四、成本测算(店群一眼看懂)
# douyin/cost_calc.py
class DouyinErpCost:
RATES = {
"cloud_inner": 0.018 / 100, # 元/次
"cloud_outer": 0.18 / 100, # 元/次
}
def monthly(self, calls_per_day: int, shops: int, env: str, days=30):
if env not in self.RATES:
raise ValueError(env)
unit = self.RATES[env]
total_calls = calls_per_day * shops * days
return total_calls * unit
if __name__ == "__main__":
c = DouyinErpCost()
# 单店日 1 万次发布类调用
print("云内 1店:", c.monthly(10_000, 1, "cloud_inner")) # 54.0
print("云外 1店:", c.monthly(10_000, 1, "cloud_outer")) # 540.0
print("云内 20店:", c.monthly(10_000, 20, "cloud_inner")) # 1080.0
print("云外 20店:", c.monthly(10_000, 20, "cloud_outer")) # 10800.0店群场景:
100 店 × 日 3000 发品调用
云内:≈ ¥1620 / 月
云外:≈ ¥16200 / 月
云外不是“贵一点”,是把商品发布 ERP 的利润模型打穿。
五、抖店签名 Client(method + timestamp 秒级)
# douyin/client.py
import hashlib
import time
import requests
class DouyinOpenClient:
GATEWAY = "https://openapi-fxg.jinritemai.com/"
def __init__(self, app_key, app_secret, access_token=None, timeout=5):
self.app_key = app_key
self.app_secret = app_secret
self.access_token = access_token
self.timeout = timeout
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
def _sign(self, params: dict) -> str:
flat = {k: v for k, v in params.items() if v is not None and k != "sign"}
qs = "".join(f"{k}{v}" for k, v in sorted(flat.items()))
raw = self.app_secret + qs + self.app_secret
return hashlib.md5(raw.encode("utf-8")).hexdigest().upper()
def execute(self, method: str, biz: dict):
params = {
"app_key": self.app_key,
"method": method,
"timestamp": str(int(time.time())),
"v": "2.0",
"sign_method": "md5",
"format": "json",
}
if self.access_token:
params["access_token"] = self.access_token
params.update(biz)
params["sign"] = self._sign(params)
resp = requests.post(self.GATEWAY, data=params, timeout=self.timeout)
return resp.json()⚠️ 抖店:
时间戳秒级
app_secret头尾包公共参数 + 业务参数一起排
和拼多多很像,但 gateway / method 命名体系不同
六、预充值余额守卫(和拼多多同思路,但按月扣)
# douyin/balance_guard.py
class DouyinBalanceGuard:
def __init__(self, redis, client,
warn_yuan=200.0, stop_yuan=50.0, alarm=None):
self.r = redis
self.client = client
self.warn = warn_yuan
self.stop = stop_yuan
self.alarm = alarm
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
def cached(self):
v = self.r.get("douyin:balance")
return float(v) if v else 999999.0
def refresh(self):
# 调开放平台账户/费用查询接口(伪代码)
resp = self.client.execute("open.account.balance.query", {})
bal = float(resp["data"]["balance"])
self.r.set("douyin:balance", bal, ex=120)
return bal
def pre_check(self, is_paid_api=True):
if not is_paid_api:
return
bal = self.cached()
if bal <= self.stop:
self.alarm and self.alarm(f"抖店余额熔断: {bal}")
raise CircuitOpen("douyin balance too low")
if bal <= self.warn:
self.alarm and self.alarm(f"抖店余额预警: {bal}")规则:
订单推送(免费):照常消费
addV2 / addSchema / 收费详情:先过 guard
欠费不是限流,是发品链路整段熄火
七、发品降本:把“N 次散弹”合并成“1 次收费”
# douyin/product_publisher.py
class ProductPublisher:
def __init__(self, client, guard, bucket):
self.client = client
self.guard = guard
self.bucket = bucket
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
def publish_batch(self, products: list):
# 1) 免费前置校验
pre = self.client.execute("/product/publishPreCheck", {
"products": products
})
valid = [p for p in products if pre_ok(pre, p)]
if not valid:
return []
# 2) 批量查 SPU 是否存在(摊薄)
existing = self.batch_spu_query([p["outer_spu_id"] for p in valid])
# 3) 同源商品先建 schema 草稿
drafts = self.build_schema_drafts(valid)
# 4) 只对新 SPU 调 addV2
for p in drafts:
if p["spu_id"] in existing:
continue
self.guard.pre_check(is_paid_api=True)
self.bucket.acquire()
self.client.execute("/product/addV2", p)
def batch_spu_query(self, outer_ids: list):
out = {}
for i in range(0, len(outer_ids), 50):
chunk = outer_ids[i:i+50]
resp = self.client.execute("/spu/query", {"outer_spu_ids": chunk})
out.update(parse_spu(resp))
return out
def build_schema_drafts(self, products):
# 同源(同图/同详情/不同规格)合成一个 schema
groups = group_by_template(products)
drafts = []
for g in groups:
self.guard.pre_check(is_paid_api=True)
self.bucket.acquire()
d = self.client.execute("/product/addSchema", g)
drafts.append(d)
return drafts降本公式(经验):
散弹式:preCheck(0?) + spu查×N + addV2×N + detail×N 合并式:preCheck(1) + spu查(N/50) + addSchema(组数) + addV2(新SPU数) + listQuery(1/20)
铺货型 ERP 通常能砍掉 60%~75% 收费调用。
八、订单侧:推送为主,轮询兜底
抖店数据推送(免费) └─ 订单/售后变更 → RDS └─ ERP 读库 + 状态机 每 5~10 min: /order/searchList(收费基础API) └─ 补漏单/晚到事件 详情: /order/orderDetail └─ 真相源,别拿列表写业务
和淘宝 DSS、京东 JMQ 同构:
推送/消息 = 触发器,列表 = 兜底,详情 = 法官。
九、云内部署决策(抖店比拼多多更硬)
场景 | 建议 |
|---|---|
自研单店 ERP | 云外能跑,但发品/订单量大就亏 |
铺货/店群/选品微应用 | 必须抖店云内 |
订单地址/手机解密 | 云外直接无权限(和淘宝增值/拼多多增值同逻辑) |
大促 | 云内 + 推送 + 限流桶 + 余额守卫 |
架构:
抖店云内 ECS ├─ DyBaseClient 基础API(订单/商品/库存) 令牌桶 ├─ DyAdvClient 增值API(解密) 单独AppKey + 强制云内 ├─ PushConsumer 数据推送 → RDS 免费 └─ Redis 幂等键 / 日调用计数 / 余额缓存
十、错误分类(抖店特有)
现象 | 处理 |
|---|---|
sign invalid | secret/排序/时间戳 |
access_token expired | 刷新 1 次 |
no permission / 非云内调用 | 增值 API 别云外调 |
系统错误/余额类 | 熔断 + 充值,不重试业务 |
限流 | 退避 |
网络超时 | 退避,但别当“发布失败”直接重发(会双发) |
发品审核挂起 | 不是接口错,进人工/异步审核流 |
发品最阴的 bug:
超时 → 你重试 addV2 → 同商品发两次 → 重复 SPU / 类目违规 / 被平台判铺货异常。
解决:
idempotency_key = sha1(shop_id + outer_spu_id + spec_fingerprint) if dedup.exists(idempotency_key): return existing_product
十一、和前几篇收口
1688:基础免费,QPS 卡脖,签名 secret 头尾
淘宝 TOP:聚石塔内外 10 倍,DSS 推送免费
京东 JOS:云鼎内稳,POP 时间窗滚动
拼多多:预充值,云外 ×10,增值禁外
抖店:预充值 + 云外 ×10 + 商品发布 2026.7.1 起收费 + 数据推送免费
一句话:
抖店 2026.7.1 之前,铺货 ERP 的潜规则是“商品发布不要钱,拼命发”;2026.7.1 之后,规则变成“发一次就计费,云外发一次顶云内十次,欠费不是限流是断气”。能活下来的抖店 ERP 不是“能发品”,而是:前置校验拦废单、SPU 批量查、schema 并草稿、addV2 只发新、推送替轮询、余额守卫在 Client 层。