# ASIN 分析 API — Agent 调用文档

> 将本文件完整提供给 Agent、AI 助手或 vibe coding 工具。Agent 应根据以下接口契约提交 ASIN 分析任务、轮询状态，并下载最终 XLSX 文件。

## 1. Agent 执行规则

1. 优先从安全环境变量获取 API Key，不得把 Key 写入源码、日志或最终报告。用户也可以直接在聊天中发送 Key，但聊天记录、截屏或会话共享都可能造成泄露，**不推荐这样做**；也可以临时保存到本地权限受限文件中，但明文文件仍有被误传、备份或其他程序读取的风险，**同样不推荐**。
2. 单个 ASIN 使用 `POST /tasks`；2–10 个 ASIN 使用 `POST /tasks/batch`。
3. HTTP 202 仅代表任务已受理。必须保存响应中的 `task_id`，不要保持 HTTP 长连接等待。
4. 不要让 Agent 会话持续等待或高频查询。优先创建独立后台监控程序或定时任务，每 5 分钟查询一次；Agent 会话可以结束，监控程序在终态时通过当前 Agent 平台支持的通知、任务唤醒或消息推送能力主动告知用户。
5. `status=success` 且 `file_available=true` 后，调用文件信息接口取得 `download_url`，再下载 XLSX。
6. `status=failed` 或 `status=timeout` 时读取 `error`，向用户说明原因；只有用户或既定工作流要求时才重新提交新任务。
7. 不得猜测任务已完成，不得枚举其他用户的任务 ID，不得向无关服务发送完整下载链接。
8. 如果当前 Agent 平台不支持后台任务、会话唤醒或主动推送，必须在提交前明确告知用户，保存 `task_id` 并约定用户稍后回来查询；不得声称会主动通知却直接停止。
9. 提交任务前，Agent 必须向用户完整转述采集配置和分析配置的全部可选参数，且任何参数都必须用中文名称说明（例如 五点、评价、难易、市场、竞争、利润、开发、广告、文案、视觉、经营、决策），不得只回答 `basic`、`reviews` 这类原始英文字段名或值。
10. 基础分析是每个任务的必选项，不要让用户选择是否开启基础分析。用户实际可选项只有：采集配置中的 五点、评价、难易，以及分析配置中的 市场、竞争、利润、开发、广告、文案、视觉、经营、决策。
11. “决策分析”可独立运行；同一任务中已启用的其它专项报告会作为可选增强输入。
12. 返回的 XLSX 文件中，第一个工作表是数据表，其后其它工作表以各个 AI 分析的配置名称命名。如果提交了某个 AI 分析，但文件中没有出现对应工作表，说明暂无该项分析结果，可能是数据不足以支撑分析，应向用户如实说明。
13. 最终生成文件后，最终输出必须包含字符串形式的完整文件路径（例如 `C:\results\B0XXXXXXXX-US-分析结果.xlsx`）。不要把路径转义为可打开的文件对象或链接，否则用户无法看到具体路径；必须以纯文本字符串输出，确保用户能直接看到并复制完整路径。
14. 与用户交流中，字段必须附带中文表达（例如 `task_id`（任务 ID）），不要只输出原始英文字段名。汇报任务阶段时不要说 `stage1`、`stage2`，也不要输出 `queued`、`success` 等原始值，应使用中文状态：排队中、待分析、分析中、已完成、失败、超时。

## 2. 服务信息

| 项目 | 值 |
| --- | --- |
| Base URL | `https://cy126.com/openapi/v1` |
| 数据格式 | UTF-8 JSON |
| 任务模式 | 异步任务 + 状态轮询 |
| 常见耗时 | 30–60 分钟；队列繁忙时可能更久 |
| 建议轮询间隔 | 300 秒 |
| 每批最大任务数 | 10 |
| 支持站点 | `US`、`JP` |
| 使用额度 | 初始100永久积分；基础8分，可选项各1分，全选20分；管理员免费 |

## 3. 鉴权

普通 API 请求支持以下任一种方式，推荐 Bearer Header：

```http
Authorization: Bearer YOUR_API_KEY
```

或：

```http
X-API-Key: YOUR_API_KEY
```

文件直链使用 `ticket` 短期签名票据，限定当前任务、5 分钟有效，通过 HTTPS 下载。过期后重新调用文件信息接口获取直链；不要记录完整 URL。

Key 重置后旧 Key 和旧下载 URL 立即失效。任务 ID 不变时，可使用新 Key 重新调用文件信息接口获取新链接。

### API Key 提供方式（按推荐顺序）

1. **环境变量（推荐）**：例如 `ASIN_API_KEY`。避免出现在代码、命令历史和最终回复中。
2. **系统密钥链或 Agent 的 Secret 管理功能（推荐）**：若运行环境支持，应优先使用。
3. **本地权限受限文件（不安全）**：仅作为临时兼容方案；文件应位于用户私有目录、限制读取权限并在任务完成后安全删除。明文文件仍可能被同步、备份或恶意程序读取。
4. **直接发送到聊天（不安全）**：可以使用，但 Key 会进入聊天记录，并可能被截屏、导出或共享。仅在用户理解风险且没有更安全方式时使用；不要在后续回复中复述 Key。

## 3.1 后台监控、定时查询与主动通知

任务通常需要 30–60 分钟。最节省 Agent token 的方式不是让对话模型反复轮询，而是让普通后台程序或平台定时任务负责查询：

1. 提交任务后持久化保存 `task_id`、用户可识别的 ASIN 和查询所需凭据引用（不要复制明文 Key 到状态日志）。
2. 启动独立监控程序，或创建每 5 分钟执行一次的定时任务。每次仅调用一次 `GET /tasks/{task_id}`；网络失败采用退避重试，不要缩短轮询间隔。
3. 返回 `terminal=false` 时立即退出本轮执行，等待下次调度，不消耗会话 token 持续等待。
4. 返回 `success` 时获取并下载 XLSX；返回 `failed` 或 `timeout` 时记录 `error`。随后停止并清理对应定时任务。
5. 通过 Agent 平台实际支持的机制主动通知用户，例如任务唤醒、系统通知、Webhook 或向原会话发送消息。通知中包含任务 ID、ASIN、最终状态和文件位置，但不包含 Key 或完整下载 URL。

后台程序本身不会自动获得“向原聊天发消息”的能力。Agent 必须先确认所用平台提供了可调用的通知或会话唤醒接口；若没有，只能保留任务状态供用户下次查询。对于支持子代理、后台任务或定时自动化的平台，应优先使用平台原生机制，而不是保持 Agent 会话运行。

## 4. 公共响应字段

每个鉴权成功的 JSON 响应都会附带：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `usage.used` | decimal string | 累计净消耗积分（包含消耗） |
| `usage.limit` | decimal string | 累计净消耗加可用积分，兼容字段 |
| `usage.remaining` | decimal string / null | 当前可用积分；超级用户为 `null` |
| `usage.is_unlimited` | boolean | 是否不限量；超级用户为 `true` |
| `api_request_count` | integer | 当前 Key 的累计 API 请求次数 |

## 5. 任务请求结构

### 5.1 必填字段

| 字段 | 类型 | 规则 |
| --- | --- | --- |
| `asin` | string | 10 位字母或数字，服务端自动转为大写 |
| `site` | string | 仅支持 `US` 或 `JP` |
| `ai_analysis` | object | 可选；基础分析默认执行，固定8积分 |

### 5.2 collection_config

全部为可选 boolean，默认 `false`：

| 字段 | 说明 |
| --- | --- |
| `bullet_points` | 采集竞品 Listing 五点描述 |
| `reviews` | 采集竞品评价数据 |
| `ad_difficulty` | 计算关键词广告投放难度 |

### 5.3 ai_analysis

| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `basic` | 否 | 兼容字段；基础分析始终执行 |
| `ad_strategy` | 否 | 广告分析：关键词流量与广告投放策略 |
| `product_selection` | 否 | 市场分析：市场需求与趋势 |
| `visual` | 否 | 主图与视觉呈现分析 |
| `inventory` | 否 | 经营分析：库存、动销与经营表现 |
| `copy` | 否 | Listing 文案分析 |
| `development` | 否 | 产品开发方向分析 |
| `pricing` | 否 | 利润分析：利润空间、价格带与定价策略 |
| `weakness` | 否 | 竞争分析：竞争格局、竞品短板与自身改进点 |
| `strategy` | 否 | 决策分析；可独立运行，其它专项报告为可选增强输入 |

完整请求对象示例：

```json
{
  "asin": "B0XXXXXXXX",
  "site": "US",
  "collection_config": {
    "bullet_points": true,
    "reviews": true,
    "ad_difficulty": false
  },
  "ai_analysis": {
    "basic": true,
    "ad_strategy": true,
    "product_selection": false,
    "visual": false,
    "inventory": false,
    "copy": true,
    "development": false,
    "pricing": true,
    "weakness": false,
    "strategy": false
  }
}
```

## 6. 提交单个任务

`POST /tasks`

```bash
curl -X POST "https://cy126.com/openapi/v1/tasks" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "asin": "B0XXXXXXXX",
    "site": "US",
    "collection_config": {"reviews": true},
    "ai_analysis": {"basic": true, "copy": true}
  }'
```

成功响应：HTTP 202。

```json
{
  "success": true,
  "message": "任务已提交",
  "task": {
    "task_id": "a1b2c3d4e5f6",
    "asin": "B0XXXXXXXX",
    "site": "US",
    "source": "api",
    "status": "queued",
    "status_text": "排队中",
    "stage": null,
    "terminal": false,
    "archived": false,
    "submitted_at": "2026-08-24 10:00:00",
    "completed_at": null,
    "error": null,
    "file_available": false,
    "file_info_url": null,
    "collection_config": {
      "bullet_points": false,
      "reviews": true,
      "ad_difficulty": false
    },
    "ai_analysis": {
      "basic": true,
      "ad_strategy": false,
      "product_selection": false,
      "visual": false,
      "inventory": false,
      "copy": true,
      "development": false,
      "pricing": false,
      "weakness": false,
      "strategy": false
    }
  },
  "duration_notice": "任务通常需要 30-60 分钟，建议每 5 分钟轮询一次状态",
  "usage": {
    "used": "20",
    "limit": "100",
    "remaining": "80",
    "is_unlimited": false
  },
  "api_request_count": 1
}
```

处理服务器离线时仍可能返回 HTTP 202，此时 `status=waiting`；任务会在服务恢复后自动执行。

## 7. 批量提交任务

`POST /tasks/batch`

每批 1–10 个任务。每个数组元素与单个任务请求结构完全一致。任一元素校验失败会拒绝整批请求；校验通过后，如果个别任务被处理服务拒绝，会出现在 `failed` 数组中。

```bash
curl -X POST "https://cy126.com/openapi/v1/tasks/batch" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tasks": [
      {
        "asin": "B0XXXXXXXX",
        "site": "US",
        "ai_analysis": {"basic": true, "copy": true}
      },
      {
        "asin": "B0YYYYYYYY",
        "site": "JP",
        "collection_config": {"reviews": true},
        "ai_analysis": {"basic": true}
      }
    ]
  }'
```

成功响应：HTTP 202。

| 字段 | 说明 |
| --- | --- |
| `tasks` | 已创建的任务对象数组，顺序与请求一致 |
| `failed` | 被处理服务拒绝的任务；正常时为空数组 |
| `duration_notice` | 任务耗时与轮询提示 |

## 8. 查询单个任务

`GET /tasks/{task_id}`

```bash
curl "https://cy126.com/openapi/v1/tasks/a1b2c3d4e5f6" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

任务对象关键字段：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `task_id` | string | 任务唯一 ID |
| `source` | string | `web` 或 `api` |
| `status` | string | 机器可读状态 |
| `status_text` | string | 面向用户的中文状态 |
| `stage` | string / null | `stage1` 数据采集、`stage2` AI 分析 |
| `terminal` | boolean | 是否为终态 |
| `archived` | boolean | 是否已在 Web 归档 |
| `error` | string / null | 失败或超时原因 |
| `file_available` | boolean | XLSX 是否就绪 |
| `file_info_url` | string / null | 文件信息接口 URL |

## 9. 分页查询任务

`GET /tasks`

```bash
curl "https://cy126.com/openapi/v1/tasks?page=1&page_size=50&source=api" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

查询参数：

| 参数 | 必填 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `page` | 否 | `1` | 页码，从 1 开始 |
| `page_size` | 否 | `50` | 每页 1–100 条 |
| `status` | 否 | — | 按任务状态筛选 |
| `source` | 否 | — | `web` 或 `api` |

响应包含 `tasks` 和：

```json
{
  "pagination": {
    "page": 1,
    "page_size": 50,
    "total": 12,
    "total_pages": 1
  }
}
```

接口会返回当前用户通过 Web 和 API 创建的任务，包括已归档任务。

## 10. 任务状态机

| status | terminal | status_text / 含义 | Agent 行为 |
| --- | --- | --- | --- |
| `waiting` | false | 等待中；服务离线，任务已持久化 | 继续轮询 |
| `queued` | false | 排队中 | 继续轮询 |
| `running` | false | 获取中、分析中、待分析或执行中 | 继续轮询 |
| `downloading` | false | 结果文件同步中 | 继续轮询 |
| `success` | true | 已完成 | 获取文件信息并下载 |
| `failed` | true | 失败 | 读取 `error` 并报告 |
| `timeout` | true | 超时 | 读取 `error` 并报告 |

任务本身不设置普通执行超时。爬虫服务连续离线超过 60 秒时，已经派发、排队或执行的任务会进入 `timeout`。失败或超时后如需重试，应创建一个新任务。

## 11. 获取文件信息

`GET /tasks/{task_id}/file`

任务必须为 `success`，且文件已经就绪。

```bash
curl "https://cy126.com/openapi/v1/tasks/a1b2c3d4e5f6/file" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

成功响应：

```json
{
  "success": true,
  "file": {
    "task_id": "a1b2c3d4e5f6",
    "filename": "B0XXXXXXXX-US-分析结果.xlsx",
    "content_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    "size_bytes": 428617,
    "download_url": "https://cy126.com/openapi/v1/tasks/a1b2c3d4e5f6/file/download?ticket=SHORT_LIVED_TICKET",
    "auth_method": "signed_ticket",
    "expires_at": "2026-09-07T00:05:00Z"
  },
  "usage": {
    "used": "20",
    "limit": "100",
    "remaining": "80",
    "is_unlimited": false
  },
  "api_request_count": 8
}
```

## 12. 下载 XLSX

`GET /tasks/{task_id}/file/download?ticket=SHORT_LIVED_TICKET`

直接请求文件信息响应中的完整 `download_url`：

```bash
curl -L "DOWNLOAD_URL_FROM_FILE_RESPONSE" -o result.xlsx
```

成功时返回：

- HTTP 200
- `Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
- `Content-Disposition: attachment`
- XLSX 二进制文件

Agent 应检查下载 URL 的主机仍为 `cy126.com`，路径仍为当前任务的 `/file/download`，然后再发送包含 Key 的请求。

## 13. API 能力边界

当前公开 API 只提供以下能力：

- 提交单个任务
- 批量提交 1–10 个任务
- 查询单个任务
- 分页及筛选查询任务
- 获取最终 XLSX 文件信息
- 下载最终 XLSX 文件

公开 API 不提供取消、归档、原任务重试、中间数据表或单独 AI Markdown 结果接口。需要重试时应创建新任务；归档等管理操作在 Web 端完成。Agent 不得猜测或调用文档未定义的路径。

## 14. 错误结构与错误码

统一错误结构：

```json
{
  "success": false,
  "error": {
    "code": "invalid_asin",
    "message": "asin 必须是 10 位字母或数字"
  },
  "usage": {
    "used": "20",
    "limit": "100",
    "remaining": "80",
    "is_unlimited": false
  },
  "api_request_count": 9
}
```

只有无法完成鉴权的 401 响应中，`usage` 和 `api_request_count` 才为 `null`。

| HTTP | code | 处理方式 |
| --- | --- | --- |
| 400 | `invalid_asin` | 修正为 10 位字母或数字 |
| 400 | `invalid_site` | 改为 `US` 或 `JP` |
| 400 | `invalid_config` | 检查对象、boolean 类型、`basic` 和 `strategy` 约束 |
| 400 | `invalid_status` | 修正状态筛选值 |
| 400 | `invalid_source` | 改为 `web` 或 `api` |
| 400 | `invalid_pagination` | 使用有效整数分页参数 |
| 401 | `missing_api_key` | 提供 API Key |
| 401 | `invalid_or_disabled_key` | 更换当前有效 Key |
| 404 | `task_not_found` | 任务不存在或不属于当前 Key 用户 |
| 404 | `file_not_found` | 文件未就绪或已丢失 |
| 409 | `task_not_ready` | 继续轮询任务状态 |
| 429 | `quota_exceeded` | 积分不足；减少勾选项或联系客服补分 |
| 502 | `upstream_rejected` | 读取消息并报告处理服务拒绝原因 |
| 502 | `upstream_unavailable` | 稍后重试提交 |

## 15. Python 完整流程示例

```python
import os
import time
from pathlib import Path
from urllib.parse import urlsplit

import requests

BASE_URL = "https://cy126.com/openapi/v1"
API_KEY = os.environ["ASIN_API_KEY"]
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

created = requests.post(
    f"{BASE_URL}/tasks",
    headers=HEADERS,
    json={
        "asin": "B0XXXXXXXX",
        "site": "US",
        "collection_config": {"reviews": True},
        "ai_analysis": {"basic": True, "copy": True},
    },
    timeout=30,
)
created.raise_for_status()
task_id = created.json()["task"]["task_id"]

while True:
    response = requests.get(f"{BASE_URL}/tasks/{task_id}", headers=HEADERS, timeout=30)
    response.raise_for_status()
    task = response.json()["task"]
    if task["status"] == "success":
        break
    if task["terminal"]:
        raise RuntimeError(task.get("error") or task["status"])
    time.sleep(300)

info_response = requests.get(f"{BASE_URL}/tasks/{task_id}/file", headers=HEADERS, timeout=30)
info_response.raise_for_status()
file_info = info_response.json()["file"]

download_url = file_info["download_url"]
parsed = urlsplit(download_url)
expected_path = f"/openapi/v1/tasks/{task_id}/file/download"
if parsed.hostname != "cy126.com" or parsed.path != expected_path:
    raise RuntimeError("下载地址校验失败")

file_response = requests.get(download_url, timeout=180)
file_response.raise_for_status()
output = Path(file_info["filename"]).name
Path(output).write_bytes(file_response.content)
print({"task_id": task_id, "file": output, "size_bytes": len(file_response.content)})
```

## 16. Agent 最终输出建议

调用完成后向用户返回简洁、可核验的信息：

```text
任务 ID：a1b2c3d4e5f6
ASIN：B0XXXXXXXX
站点：US
最终状态：已完成
文件名：B0XXXXXXXX-US-分析结果.xlsx
保存位置：C:\results\B0XXXXXXXX-US-分析结果.xlsx
```

输出要求：

1. 保存位置必须输出字符串形式的完整文件路径（含盘符与目录的绝对路径），不要只给出文件对象、可点击链接或被转义的路径，确保用户能直接看到并复制完整路径。Agent 有时会把路径识别为可打开的文件并转义，导致用户不知道具体路径，必须避免这种情况。
2. 最终状态必须使用中文表达（已完成 / 失败 / 超时），不要输出 `success`、`failed`、`timeout` 等原始值。
3. 所有字段必须附带中文含义（例如 任务 ID、ASIN、站点、最终状态、文件名、保存位置），不要使用原始英文字段名。
4. 如果提交了某个 AI 分析但结果文件中没有对应工作表，应告知用户暂无该项分析结果，可能是数据不足以支撑分析。
5. 不要在最终输出中包含 API Key 或完整 `download_url`。


## 积分与会员（新版）

Web/API共用：基础分析强制执行8分，3项采集和9项AI配置各1分，全选20分，无每日任务数量上限。`usage.balance`、`temporary`、`permanent`为精确十进制字符串，`remaining`管理员为null；`unit`固定points。`used/limit`为兼容字段，。`usage.memberships`含会员周期，`batches`含来源、余额、到期时间及转存资格，`ledger`含最近100笔记录。`billing`含cost、refunded、net、settled、items及refunded_items。

标准会员99元/30个自然日，每日100分；高级会员199元，每日300分。开通立即发首批，随后北京时间每日00:00发放，每批24小时，允许首两批重叠。按批到期未用部分20%转永久；续订排队，不支持中途换套餐。初始永久积分100，。

失败/超时全额返还积分；成功任务已选AI无结果退该项1分。已过期订阅积分退为24小时补偿批次，从实际退款时间起算，到期剩余再按20%转永久。管理员有期限补分不转存。会员套餐费用退款由客服处理。

文件响应提供X-Points-Balance、X-Points-Temporary、X-Points-Permanent；旧X-Usage-*头的单位改为积分，X-Usage-Unit=points。积分不足返回429 quota_exceeded。重试创建新任务重新计费，原任务返还幂等；相同Idempotency-Key不重复扣分。
