API文档(采集对接 · SaaS 多租户版)
本页面向采集合作方:只包含 4 类数据的拉取与回推接口。系统已升级为多用户 SaaS,数据按用户隔离。
对接须知
鉴权:所有采集接口统一用请求头
返回格式:所有接口返回
任务归属:平台级密钥(scope=platform)可一次领取全部用户的任务,返回行带
任务可能少于"待采总数":同一件商品 / 同一个店铺 / 同一个关键词被多个用户同时追踪时, 系统只会下发一条任务(跨用户去重),采集结果由系统自动分发给他们。 计费口径:只向"需要采集数据"的用户计费 —— 对方本轮也在自己的采集周期内则照常扣费, 不在采集周期内则数据照给、免费共享。这是预期行为,不是漏发。
批次号:
平台权限(按密钥配置):一个密钥可以被限定为只能采某几个平台(如只会采虾皮、只会采亚马逊, 由运营方在后台勾选)。
· 拉取:只返回该密钥被授权平台的任务,返回体里的
· 回推:非授权平台的数据会被
· 每个平台各有一条独立的任务批次,互不影响 —— 虾皮采集方与亚马逊采集方可以同时跑同一个用户的任务。
X-Api-Key: <采集密钥>(也兼容 ?api_key= 参数)。
密钥由运营方发放,请勿写入前端代码或公开仓库。返回格式:所有接口返回
{code, msg, data},code=0 表示成功。
401=密钥缺失或失效,403=无权限(用户被禁 / 授权无效 / IP 被封 / 该密钥未授权此平台),429=触发频率限制。任务归属:平台级密钥(scope=platform)可一次领取全部用户的任务,返回行带
user_id 与 shop_id,
回传时按店铺 / 链接自动归属到对应用户,一般无需关心 user_id;任务可能少于"待采总数":同一件商品 / 同一个店铺 / 同一个关键词被多个用户同时追踪时, 系统只会下发一条任务(跨用户去重),采集结果由系统自动分发给他们。 计费口径:只向"需要采集数据"的用户计费 —— 对方本轮也在自己的采集周期内则照常扣费, 不在采集周期内则数据照给、免费共享。这是预期行为,不是漏发。
批次号:
claim=1 时系统生成批次号并返回(详情 B / 评论 R / 关键词 K 前缀),
回传时带上 collect_batch 便于对账。平台权限(按密钥配置):一个密钥可以被限定为只能采某几个平台(如只会采虾皮、只会采亚马逊, 由运营方在后台勾选)。
· 拉取:只返回该密钥被授权平台的任务,返回体里的
platforms 字段就是你的平台范围
("all" 表示不限);可用 platform=shopee 进一步只拉某一个平台
(多平台采集机可以分流,互不抢其它平台的任务)。· 回推:非授权平台的数据会被
403 拒绝,且不入库、不扣费。
这种拒绝是"用错密钥",不要自动重试,请改用对应平台的密钥或联系运营方调整权限。· 每个平台各有一条独立的任务批次,互不影响 —— 虾皮采集方与亚马逊采集方可以同时跑同一个用户的任务。
接口一览(4 类数据 · 拉取 + 回推)
| 数据类型 | 拉取任务(GET) | 回推结果(POST) |
|---|---|---|
| 链接详情 | api/collect.php?action=list&type=detail&claim=1 |
api/callback.php |
| 评论 | api/collect.php?action=list&type=review&claim=1 |
api/review_callback.php |
| 店铺 | api/shop_collect.php?action=list |
api/shop_callback.php |
| 关键词 | api/keyword_collect.php?action=list&claim=1 |
api/keyword_callback.php |
调用顺序:先 拉取 拿到任务(带
link_id / keyword_id 等定位标识),采集完成后按同一批标识 回推;
回推接口统一使用 Content-Type: application/json。下面按数据类型逐组说明。1链接详情 拉取任务 → 回推采集结果
GET
api/collect.php?action=list&scope=need&claim=1&type=detail&limit=50
功能
获取当前密钥用户的待采集商品链接。按用户隔离;仅返回已标记待采集或采集频率已到期、且开关开启、且不在失败冷却窗口内的链接;用户积分不足 / 授权失效时返回空列表(msg 里会写明 reason)。type=detail 详情采集 / type=review 评论采集,两类独立维护批次与状态。claim=1 自动生成批次号。
「失败冷却窗口」= 上一次回推被判为采集失败后,系统给它安排的静候期(默认 30 分钟,可在后台调整),到期后自动重新排入任务。
「失败冷却窗口」= 上一次回推被判为采集失败后,系统给它安排的静候期(默认 30 分钟,可在后台调整),到期后自动重新排入任务。
请求头
X-Api-Key: ckxxxxxxxx请求参数
| 参数 | 必填 | 说明 |
|---|---|---|
| action | 是 | list=拉取待采集;history=历史批次(传 link_id) |
| type | 否 | detail(默认)=详情,review=评论 |
| scope | 否 | need(默认)=已标记待采集 或 采集频率到期(且不在失败冷却中);marked=仅标记待采集;all=全部(诊断用,不做跨用户去重过滤) |
| claim | 否 | 1=领取并生成批次号(详情B前缀/评论R前缀) |
| limit | 否 | 默认50,最大500 |
| batch | 否 | 指定批次号继续拉取未完成部分 |
| mode | 否 | push=只领取「主动触发」的任务(仅限后台配成主动触发的平台),返回行会带 trigger;不传=只领取普通拉取的任务 |
| user_id | 否 | 平台级密钥下可选,只领取指定用户的任务 |
返回要点
link_id / user_id / shop_id / product_link / product_id /
site_name / collect_batch / pending_total;用户密钥模式下额外回带
credit / license_active,便于采集端提示"积分不足 / 授权到期"。店铺相关字段(2026-09-29 新增,采集方按店铺抓整店链接用):
| 字段 | 说明 |
|---|---|
| shop_username | 店铺账号名(= 店铺名,如 mrsexshop)。用它打开店铺主页就能把该店所有外显链接一次抓回来 |
| username_known | true=店铺名已有值可直接用;false=还没采集到,此时请用 shop_url(数字ID版店铺主页) |
| shop_url | 店铺主页链接 https://shopee.tw/shop/<platform_shop_id>,不依赖店铺名,永远可用 |
| shop_avatar_url | 店铺头像 |
| shop_name / shop_display_name | 备注名 / 平台真实店名(展示用,不适合当标识) |
POST
api/callback.php
功能
回推商品详情采集结果(1.json 格式 payload),解析入库并按单价扣减用户积分,写入流水 collect_detail。
若该商品正被其他用户追踪,系统会把本次结果自动分发给他们:对方本轮也在自己的采集周期内 → 照常计费;
不在采集周期内 → 数据照给但不计费(免费共享)。响应里的
shared_users 是共享到的总人数,
shared_free_users 是其中免费共享的人数,采集方不需要做任何额外动作。回推准入规则(重要)
系统在入库前会先判两道,命中即不入库、不扣费,但仍然返回
·
·
采集失败时请照实回推错误(不要回推空壳/占位数据):系统会记失败状态并安排稍后重试, 比推一条空数据更有利于把问题暴露出来。
code:0
(收到但不采纳,请勿重试)。用 accepted 与 skip_reason 区分:·
skip_reason=collect_failed:payload 里自报 status=error/
error_msg,或根本解析不到商品ID与标题 → 判为采集失败。系统会把该链接标成
「采集失败」并进入冷却窗口(默认 30 分钟,之后自动重试),这轮不写任何详情、不扣费。·
skip_reason=duplicate_retry:同一条链接的同一个 collect_batch 已经成功回推过,
或者没带批次号而该链接本轮已完成且未到采集周期 → 判为重复推送。采集失败时请照实回推错误(不要回推空壳/占位数据):系统会记失败状态并安排稍后重试, 比推一条空数据更有利于把问题暴露出来。
请求头
X-Api-Key: ckxxxxxxxx Content-Type: application/json请求体参数
| 参数 | 必填 | 说明 |
|---|---|---|
| payload | 是 | 1.json 结构原始数据(item / product_review / shop_detailed / description_info) |
| link_id | 否 | 链接id,缺省按 product_id 自动匹配(仅匹配当前用户的链接) |
| shop_id / product_id / product_link | 否 | 辅助匹配字段 |
| user_id | 否 | 平台级密钥下可选,同一商品被多用户追踪时用于指定归属 |
| collect_batch | 否 | 详情批次号,用于推进批次进度并作为判重凭据(强烈建议带上) |
返回要点
accepted(true=已采纳入库;false=已收到但未采纳)/ skip_reason / reason(未采纳的具体原因)/
detail_id / shared_users(共享到的总人数)/ shared_free_users(其中免费共享人数)/
credit_deducted(本次扣费,未采纳时为 0)/ credit_balance(扣减后余额)2评论 拉取任务 → 回推采集结果
GET
api/collect.php?action=list&scope=need&claim=1&type=review&limit=50
功能
拉取待采集评论的商品链接。与详情拉取是同一个接口,只是把
type 换成 review:
评论有独立的开关、频率、批次(R 前缀)与完成状态,因此同一件商品可能"详情已采、评论还没采"。请求头
X-Api-Key: ckxxxxxxxx请求参数
参数与「链接详情拉取」完全一致,仅
type=review;返回行额外带评论相关状态,定位用 link_id / product_id / shop_id。
POST
api/review_callback.php
功能
回推评论采集结果(reviews 数组),逐条入库并按单价扣减用户积分(一轮扣一次,不按条数),写入流水 collect_review。
同样支持跨用户分发(响应
shared_users / shared_free_users)。回推准入规则(重要,与商品详情同一套口径)
入库前先判两道,命中即不入库、不扣费,但仍返回
·
·
建议一定带上 collect_batch:它是判重的凭据;不带就只能靠"本轮是否已完成"来兜底。
code:0:·
skip_reason=collect_failed:payload 自报 error/timeout,或这轮评论里
没有一条是有效内容(没内容、没昵称、没星级全被过滤)→ 判为采集失败,
标「评论采集失败」并进入冷却窗口(默认 30 分钟)。空壳评论不会写进库。·
skip_reason=duplicate_retry:该链接的同一个 collect_batch 已经回推过评论
(或没带批次号而本轮评论已完成且未到采集周期)→ 判为重复推送。建议一定带上 collect_batch:它是判重的凭据;不带就只能靠"本轮是否已完成"来兜底。
请求头
X-Api-Key: ckxxxxxxxx Content-Type: application/json请求体参数
| 参数 | 必填 | 说明 |
|---|---|---|
| reviews | 是 | 评论数组(reviewer_name / rating_star / review_content / review_sku / review_time) |
| link_id | 否 | 链接id,缺省按 product_id + shop_id 匹配(仅当前用户) |
| user_id | 否 | 平台级密钥下可选,指定归属用户 |
| collect_batch | 否 | 评论批次号(R前缀)并作为判重凭据(强烈建议带上) |
返回要点
accepted / skip_reason / reason / review_inserted(实际入库条数)/
shared_users / shared_free_users / credit_deducted / credit_balance3店铺 拉取任务 → 回推采集结果
GET
api/shop_collect.php?action=list&limit=50
功能
拉取需要采集店铺用户名的店铺(与详情批次联动)。同一个平台店铺被多用户追踪时只下发一条任务。
店铺名字段说明(重要):
详情采集任务(
username 就是店铺账号名(如 mrsexshop),
采集方拿到它就能打开 https://shopee.tw/{username} 把这家店的所有外显链接一次抓回来。详情采集任务(
collect.php)的每一行也已带 shop_username / username_known / shop_url,
一般不需要再单独调本接口查店名。请求头
X-Api-Key: ckxxxxxxxx请求参数
| 参数 | 必填 | 说明 |
|---|---|---|
| action | 否 | list(默认)拉取"待采集用户名"的任务; shops 只读查询店铺清单(不计费、不改状态、不限批次是否在跑) |
| batch | 否 | 指定详情批次号;不传则自动取进行中的详情批次 |
| limit | 否 | 默认50,最大500 |
| user_id | 否 | 平台级密钥下可选,只拉取指定用户的店铺 |
| link_id | 否 | 仅 action=shops:按商品链接ID反查它所属的店铺(最常用的用法) |
| shop_id | 否 | 仅 action=shops:按平台店铺ID单店查询 |
| keyword | 否 | 仅 action=shops:按备注店名 / 平台店名 / 店铺账号名 模糊搜索 |
返回字段(list 与 shops 一致)
| 字段 | 说明 |
|---|---|
| user_id | 店铺归属用户 |
| shop_id | 平台店铺ID |
| username | 店铺账号名(= 店铺名)。为空表示还没采集到 |
| username_known | true=我方已有该店的用户名,可直接用;false=需要先采集 |
| shop_display_name | 平台真实店名(营销长名,仅展示用,不适合当标识) |
| shop_name | 该用户自己起的备注名(如「矮胖」),仅展示用 |
| shop_link / shop_url | 店铺主页链接,只用平台店铺ID拼接 → 即使 username 还没采到也一定可用 |
| avatar_url / site_name / platform_name / collect_batch | 头像 / 站点 / 平台 / 关联的详情批次号 |
| readonly / charged(仅 shops) | readonly=true、charged=0:明确这是查询,不产生任何积分 |
list 口径(2026-09-29 放宽):返回「批次命中且未回传」∪「username 仍为空」的店铺。
后者是兜底 —— 批次已关单但店铺行还挂着旧批次号、曾回传过空用户名却被标成已采集、
或后加的从没进过批次的店,只要还没有店铺名就一定会被下发,不会再出现"永远拿不到店铺名"。
注意:店铺名已经采到手的店不会被重新塞回 list(避免重复扣用户的店铺采集费)。 要拿已采到手的店铺名,请用
注意:店铺名已经采到手的店不会被重新塞回 list(避免重复扣用户的店铺采集费)。 要拿已采到手的店铺名,请用
action=shops(只读、免费、随时可查)。
POST
api/shop_callback.php
功能
回推店铺用户名并按单价扣减用户积分(流水 collect_shop)。回推后系统自动共享给同轮追踪该店铺的其他用户(响应
shared_users)。请求头
X-Api-Key: ckxxxxxxxx Content-Type: application/json请求体参数
| 参数 | 必填 | 说明 |
|---|---|---|
| shop_id | 是 | 平台店铺ID(兼容内部id) |
| username | 是 | 采集到的用户名(店铺账号名,如 mrsexshop) |
| collect_batch | 否 | 批次号 |
| shop_name / shop_location | 否 | 一并更新(空值不会覆盖已有店名) |
username 为空时会怎样(2026-09-29 起):不计费、不改采集状态、不共享,
返回
code:0 + accepted:false + skip_reason:empty_username。
该店铺会在下一轮继续下发,等真正采到名字再回传即可 —— 请不要为了"完成任务"回推空字符串或占位名,
那只会白跑一趟(以前会把店铺永久锁成"已采集但没名字",导致再也拿不到店铺名)。
4关键词 拉取任务 → 回推搜到的链接
GET
api/keyword_collect.php?action=list&scope=need&claim=1&limit=50
功能
用户在用户端填「关键词 + 平台 + 站点 + 期望数量」后,本接口拉取待采集的关键词任务;
采集方按
keyword / platform_name / site_name 去平台搜索,把搜到的商品链接通过
keyword_callback 回推。同一个关键词被多用户追踪时只下发一条任务,回推结果自动分发给所有同轮订阅用户。请求头
X-Api-Key: ckxxxxxxxx请求参数
| 参数 | 必填 | 说明 |
|---|---|---|
| action | 否 | list(默认) |
| scope | 否 | need(默认)=待采集或频率到期;marked=仅标记待采集;all=全部(诊断用,不做去重过滤) |
| claim | 否 | 1=领取并生成批次号(K 前缀) |
| limit | 否 | 默认50,最大200 |
| batch | 否 | 指定批次号继续拉取 |
| user_id | 否 | 平台级密钥下可选,只领取指定用户的关键词任务 |
返回要点
keyword_id / user_id / keyword / platform_name /
site_name(可能为空=不限站点)/ target_count(期望采集条数)/
collect_batch / pending_total
POST
api/keyword_callback.php
功能
回推关键词搜到的商品链接(数组)。回推后系统自动完成:解析店铺ID → 该用户下没有这家店就自动建店 → 链接去重入库 → 置为「待采集详情」,
随后由
collect.php 正常下发做详情采集。请求头
X-Api-Key: ckxxxxxxxx Content-Type: application/json请求体参数
| 参数 | 必填 | 说明 |
|---|---|---|
| keyword_id | 推荐 | 拉取时返回的 keyword_id,定位最准 |
| platform_name / site_name / keyword | 否 | 不传 keyword_id 时用这三项反查任务 |
| user_id | 否 | 平台级密钥下可选,同一关键词多用户时用于指定归属 |
| collect_batch | 否 | 关键词批次号(K 前缀) |
| links | 是 | 搜到的商品链接数组。每项可为字符串,或对象
{product_link, product_id, main_image, shop_id, shop_name};
缺少商品ID/店铺ID时会尝试从虾皮链接(形如 -i.{店铺ID}.{商品ID})解析,仍解析不到的条目会被跳过 |
返回要点
received(收到条数)/ added(实际采纳并归纳的条数)/ skipped(重复或无法归属)/
new_shops(自动新建店铺数)/ shared_users(共享到的用户数)常见问题(采集方)
1. 拉到的任务数比"待采总数"少? 同一件商品 / 同一个店铺 / 同一个关键词被多个用户同时追踪时只下发一条任务(跨用户去重),
回推后系统自动分发给所有订阅用户,属预期行为。
2. 返回空列表并提示积分不足 / 授权到期? 该用户侧的前置条件不满足,任务会被临时扣住,用户充值或续费后自动恢复,采集方无需处理。
3. 同一条链接需要重复采吗? 不需要。按
4. 回推重复提交会怎样? 店铺回推是字段覆盖,重复提交无副作用; 关键词回推的链接按「店铺 + 链接」去重,已存在的会跳过(响应里计入
若响应超时不确定是否写入成功,也可以先用
5. 采不到数据(商品下架 / 超时 / 遇到验证码)该怎么回推? 照实把错误回推上来,不要回推空壳或占位数据。系统会把该链接标成「采集失败」, 记录失败原因,并进入冷却窗口(默认 30 分钟)后自动重新排入任务;这期间不写数据、不扣费。 若推的是空壳数据,系统同样会拒收(
6. 怎么拿到「店铺名」,按店铺把整店链接一次抓回来? 店铺名 =
① 详情任务的每一行已直接带
若
7. 回推一直失败怎么办? 请把响应里的
8. 一次能回传多少个商品? 可以一次回传 4~50 条。把这一批的条目放进数组即可,以下写法都支持:
·
·
· 顶层直接是数组
返回体:
每条独立处理:第 3 条坏了不影响第 4 条入库与计费。个别条目失败请不要整批重推 —— 重推会命中判重闸门(不会重复计费),但白跑一趟。
9. 什么是「主动触发」? 如果某个平台的某种数据被运营方配成了主动触发, 它不会出现在普通拉取的结果里;需要带
注意:触发器里的凭证不会随任务下发(只回
采集完的回传接口与普通链路完全相同,无需另做一套。
10. 回传的原始 JSON 存在哪? 会按
2. 返回空列表并提示积分不足 / 授权到期? 该用户侧的前置条件不满足,任务会被临时扣住,用户充值或续费后自动恢复,采集方无需处理。
3. 同一条链接需要重复采吗? 不需要。按
claim=1 返回的批次,用 batch=<批次号> 继续拉取未完成部分即可,已完成的行不会再下发。4. 回推重复提交会怎样? 店铺回推是字段覆盖,重复提交无副作用; 关键词回推的链接按「店铺 + 链接」去重,已存在的会跳过(响应里计入
skipped);
链接详情回推与评论回推现在也带判重:同一条链接的同一个 collect_batch
已经成功回推过,第二次会返回 code:0 + accepted:false + skip_reason:duplicate_retry,
不会重复入库、更不会重复扣费——这种响应说明"已收到,不需要重试",直接跳过即可。
所以:请务必带上 collect_batch,它是判重的凭据。若响应超时不确定是否写入成功,也可以先用
api/collect.php?action=history&link_id=xxx 核对最近采集时间。5. 采不到数据(商品下架 / 超时 / 遇到验证码)该怎么回推? 照实把错误回推上来,不要回推空壳或占位数据。系统会把该链接标成「采集失败」, 记录失败原因,并进入冷却窗口(默认 30 分钟)后自动重新排入任务;这期间不写数据、不扣费。 若推的是空壳数据,系统同样会拒收(
skip_reason=collect_failed)——
但失败状态与原因就记不下来了,运营方也无从判断是哪一类失败。
响应里的 reason 字段会写明这次为什么被判为失败。6. 怎么拿到「店铺名」,按店铺把整店链接一次抓回来? 店铺名 =
username(店铺账号名),例如 mrsexshop,用它打开
https://shopee.tw/{username} 即可枚举该店所有外显链接。获取途径(按优先级):① 详情任务的每一行已直接带
shop_username / username_known / shop_url(collect.php,2026-09-29 起);
② shop_collect.php?action=shops&link_id=<link_id> 按商品链接反查店铺(只读、不计费);
③ shop_collect.php?action=shops&shop_id=<平台店铺ID> 单店查询;
④ shop_collect.php?action=list 只返回"还缺用户名"的店 —— 那些店本来就是需要你去采集店铺名的任务。若
username_known=false 且任务里也没有这家店,说明店铺名还没采到,
此时用 shop_url(数字ID版店铺主页)同样能打开店铺。7. 回推一直失败怎么办? 请把响应里的
code / msg、请求时间与批次号反馈给运营方,便于按批次对账。8. 一次能回传多少个商品? 可以一次回传 4~50 条。把这一批的条目放进数组即可,以下写法都支持:
·
{"channel":"rpa","payload":[条目1,条目2,...]}(推荐)·
{"results":[...]} / items / list / data / tasks / records / details· 顶层直接是数组
[条目1,条目2,...];或 {"payload":{"results":[...]}}返回体:
data.total / accepted / skipped / failed / credit_deducted / items[],
items 里每条带 index 与自己的 accepted(失败条目还有 skip_reason 或 error)。每条独立处理:第 3 条坏了不影响第 4 条入库与计费。个别条目失败请不要整批重推 —— 重推会命中判重闸门(不会重复计费),但白跑一趟。
9. 什么是「主动触发」? 如果某个平台的某种数据被运营方配成了主动触发, 它不会出现在普通拉取的结果里;需要带
mode=push 领取。
push 链路返回的每一行会多带 collect_mode=push 与 trigger
(触发渠道:name / handler / endpoint / auth_type / has_auth / params),
你按 handler 决定走哪套接口去采。若该平台没配触发器,会返回
trigger=null 且带 trigger_hint 说明原因。注意:触发器里的凭证不会随任务下发(只回
auth_type 与 has_auth),
需要凭证时请写进触发器的「参数模板」,或在你自己程序里配置。采集完的回传接口与普通链路完全相同,无需另做一套。
10. 回传的原始 JSON 存在哪? 会按
json/{用户名}/{日期}/{批次}/{记录ID}_{字段}.json
落盘,方便按用户与批次整体导出。