> ## Documentation Index
> Fetch the complete documentation index at: https://docs.topify.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 经授权的 AI 智能体设置

> 用户授权账户、团队和项目详情后，使用具备工具调用能力的 AI 智能体设置 Topify。

<Columns cols={3}>
  <Card title="Claude Code" icon="terminal">
    使用 tool\_use 直接从 Claude Code 调用以下端点。
  </Card>

  <Card title="Cursor" icon="code">
    Cursor 的智能体模式可以通过 HTTP 请求调用这些端点。
  </Card>

  <Card title="OpenClaw" icon="robot">
    任何具备工具调用能力的 LLM 智能体都可以完成此流程。
  </Card>
</Columns>

这些端点使 AI 智能体能够使用用户明确提供或授权的账户信息，从零开始设置 Topify.ai 并生成完整的 GEO 可见度报告。

完整流程包含三次 API 调用：

1. **创建账户** —— 使用邮箱注册，立即获取凭证
2. **获取 API 密钥** —— 用凭证换取 API 密钥
3. **创建项目** —— 启动品牌跟踪并通过 webhook 接收结果

<Warning>
  请使用用户提供或明确授权的邮箱地址。智能体不得虚构临时邮箱或管理员身份。API 密钥只能由管理员创建，并且目前对整个团队拥有完整权限；暂不支持项目范围的 API 密钥。
</Warning>

<Danger>
  只能在受信任的服务端环境中运行此流程。切勿在浏览器代码、客户端应用、日志、提示词、聊天记录或对其他用户可见的工具输出中暴露生成的密码或 API 密钥。
</Danger>

<Note>
  这些端点专为可以程序化发起 HTTP 请求的 **工具调用 AI 智能体** 设计，例如 Claude Code、Cursor 和 OpenClaw。如果您使用的是无法直接调用 API 的网页版 AI 聊天机器人（ChatGPT、Perplexity 等），请在 [app.topify.ai](https://app.topify.ai) 手动创建账户和项目，然后使用您的邮箱和密码通过 **获取 API 密钥** 端点为只读数据端点获取密钥。
</Note>

***

## 额度与速率限制

每个 API 密钥都有一个**速率限制等级**和一个**月度额度配额**。当项目在引导启动和每日刷新周期中获取 AI 回复时，会消耗额度。

### 速率限制等级

速率限制使用 60 秒滑动窗口。突发额度允许您短暂超出基础速率。

| 等级       | 每分钟请求数 | 突发  | 每窗口有效限额 |
| -------- | ------ | --- | ------- |
| Standard | 60     | +10 | 70      |
| Premium  | 300    | +50 | 350     |

新创建的 API 密钥处于 **standard** 等级。如需升级到 premium，请联系我们。

当超出限额时，API 返回 `429 Too Many Requests`，并附带 `Retry-After` 请求头指示需要等待的秒数。

### 各套餐的研究额度

每个套餐都包含一个月度额度预算，决定您的项目可以运行多少次 AI 研究查询。

| 套餐                        | 月度额度  |
| ------------------------- | ----- |
| Skip Trial（API 创建账户的默认套餐） | 10    |
| Basic                     | 200   |
| Pro                       | 500   |
| Enterprise                | 2,000 |

通过 API 创建的账户默认在 **skip\_trial** 套餐上启动，拥有 10 个额度。每次项目引导启动会按照查询的搜索词和 AI 服务商数量按比例消耗额度（典型情况下 5 个搜索词 × 3 个 AI 服务商 = 完整一次引导启动消耗 15 个额度）。skip\_trial 套餐运行精简的引导启动，以适应 10 个额度的预算。如需运行包含全部搜索词和 AI 服务商的完整引导启动，请从 [仪表盘](https://app.topify.ai) 升级到 Basic 套餐或更高，或联系我们。

### 响应请求头

每个响应都包含速率限制和额度信息：

| 请求头                     | 描述                   |
| ----------------------- | -------------------- |
| `X-RateLimit-Limit`     | 当前窗口内允许的最大请求数        |
| `X-RateLimit-Remaining` | 触发限流前剩余的请求数          |
| `X-Credit-Available`    | 您的密钥剩余的研究额度          |
| `Retry-After`           | 距窗口重置的秒数（仅在 `429` 时） |

***

## 创建账户

```
POST /account/create
```

创建一个新的 Topify.ai 账户，并在 `skip_trial` 套餐下创建一个团队。账户创建后无需邮箱验证，可立即使用。

<Note>
  此端点无需认证。生成的密码仅返回一次，之后无法再次获取 —— 请妥善保管。
</Note>

### 请求体

| 字段         | 类型     | 必填  | 描述                         |
| ---------- | ------ | --- | -------------------------- |
| `email`    | string | Yes | 用户提供或明确授权的新账户邮箱地址。不要生成临时身份 |
| `password` | string | No  | 此字段会被忽略。服务端会生成安全密码         |

```json theme={null}
{
  "email": "user@example.com"
}
```

### 响应

```json theme={null}
{
  "code": 200,
  "message": "200 OK",
  "data": {
    "user_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "team_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "email": "user@example.com",
    "password": "<generated-password-returned-once>"
  }
}
```

### 响应字段

| 字段         | 类型            | 描述            |
| ---------- | ------------- | ------------- |
| `user_id`  | string (UUID) | 新用户的 ID       |
| `team_id`  | string (UUID) | 为此账户创建的团队     |
| `email`    | string        | 规范化后的邮箱地址     |
| `password` | string        | 自动生成的密码。请妥善保管 |

### 错误

| 状态    | 详情                                                               | 原因          |
| ----- | ---------------------------------------------------------------- | ----------- |
| `400` | `A valid email is required`                                      | 邮箱为空或缺少 `@` |
| `409` | `Failed to create account. The email may already be registered.` | 此邮箱的用户已存在   |

<Tip>
  **如果您收到 409：** 账户已存在。使用同一邮箱和用户已有密码跳到 **获取 API 密钥** 步骤。如果不知道密码，请询问用户或引导他们到 [app.topify.ai](https://app.topify.ai) 重置密码。
</Tip>

***

## 获取 API 密钥

```
POST /account/api-key
```

使用团队管理员的邮箱和密码进行认证，然后在 **standard** 速率限制等级上创建并返回一个新的 API 密钥。该密钥可访问所选团队拥有的所有项目；目前不签发项目级作用域的密钥。

### 请求体

| 字段         | 类型            | 必填  | 描述                      |
| ---------- | ------------- | --- | ----------------------- |
| `email`    | string        | Yes | 账户邮箱地址                  |
| `password` | string        | Yes | 账户密码（来自创建端点）            |
| `team_id`  | string (UUID) | No  | 要为其创建密钥的团队。管理员管理多个团队时必填 |

```json theme={null}
{
  "email": "user@example.com",
  "password": "<account-password>"
}
```

### 响应

```json theme={null}
{
  "code": 200,
  "message": "200 OK",
  "data": {
    "api_key": "tk_live_<your-key>",
    "team_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "key_prefix": "tk_live_214d",
    "rate_limit_tier": "standard"
  }
}
```

### 响应字段

| 字段                | 类型            | 描述                                    |
| ----------------- | ------------- | ------------------------------------- |
| `api_key`         | string        | 完整 API 密钥。仅存放在服务端密钥管理器或受保护的环境变量中      |
| `team_id`         | string (UUID) | 此密钥所属的团队                              |
| `key_prefix`      | string        | 密钥的前 12 个字符，用于标识                      |
| `rate_limit_tier` | string        | 分配给此密钥的速率限制等级（`standard` 或 `premium`） |

### 错误

| 状态    | 详情                                   | 原因                      |
| ----- | ------------------------------------ | ----------------------- |
| `401` | `Invalid email or password`          | 认证失败                    |
| `403` | `No admin team found for this user`  | 只有团队管理员可以创建或获取公共 API 密钥 |
| `400` | `team_id is required`                | 管理员管理多个团队；请指定目标团队       |
| `500` | `Authentication service unavailable` | 身份验证服务暂时不可用             |

***

## 创建项目

```
POST /account/projects
```

创建一个新的品牌跟踪项目并在后台启动引导流水线。端点会立即返回 `202 Accepted` 状态，同时流水线异步运行。

引导流水线会生成跟踪搜索词、从所有 AI 服务商获取初始 AI 回复、计算品牌指标并检测竞争对手。完成后，会向您提供的 URL 发送 webhook 回调。

<Note>
  需要通过 `X-API-Key` 请求头进行 API 密钥认证。
</Note>

### 请求体

| 字段            | 类型     | 必填  | 描述                      |
| ------------- | ------ | --- | ----------------------- |
| `brand_name`  | string | Yes | 要跟踪的品牌名称                |
| `brand_url`   | string | Yes | 品牌的网站 URL               |
| `webhook_url` | string | Yes | 用于接收完成回调的 URL           |
| `language`    | string | No  | 生成搜索词所用语言（例如 `en`、`ja`） |
| `location`    | string | No  | 目标市场国家代码（例如 `US`、`JP`）  |

```json theme={null}
{
  "brand_name": "Acme Corp",
  "brand_url": "https://acme.com",
  "webhook_url": "https://your-service.com/webhooks/topify",
  "language": "en",
  "location": "US"
}
```

### 响应

```json theme={null}
{
  "code": 202,
  "message": "202 Accepted",
  "data": {
    "project_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
    "status": "initializing"
  }
}
```

### 响应字段

| 字段           | 类型            | 描述                      |
| ------------ | ------------- | ----------------------- |
| `project_id` | string (UUID) | 新项目的 ID                 |
| `status`     | string        | 初始状态。始终为 `initializing` |

### Webhook 回调

当引导流水线完成（或失败）时，会向您的 `webhook_url` 发送一个 POST 请求，载荷如下：

**成功：**

```json theme={null}
{
  "event": "project.bootstrap",
  "project_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
  "status": "completed",
  "error": null,
  "timestamp": "2026-03-10T03:27:35Z"
}
```

**失败：**

```json theme={null}
{
  "event": "project.bootstrap",
  "project_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
  "status": "error",
  "error": "Failed to generate prompts",
  "timestamp": "2026-03-10T03:27:35Z"
}
```

<Warning>
  仅将引导启动回调视为完成信号。先将其中的 `project_id` 与创建请求返回的 ID 匹配，再通过经过身份验证的 API 请求确认当前项目状态，然后才执行任何后续写入操作。
</Warning>

### 错误

| 状态    | 详情                                                 | 原因               |
| ----- | -------------------------------------------------- | ---------------- |
| `400` | `brand_name is required`                           | 缺失或为空的品牌名称       |
| `400` | `brand_url must be a valid URL`                    | URL 校验失败         |
| `400` | `webhook_url must be a valid URL`                  | Webhook URL 校验失败 |
| `401` | `Missing X-API-Key header`                         | 未提供 API 密钥       |
| `403` | `You've reached the maximum number of projects...` | 已达到套餐项目数量上限      |

***

## 引导启动完成后

Webhook 返回 `"status": "completed"` 且您已通过经过身份验证的 API 确认项目后，使用以下只读端点（详见 [API 参考](/api-reference/introduction)）获取结果：

| 端点                                              | 返回内容                   |
| ----------------------------------------------- | ---------------------- |
| `GET /projects`                                 | 项目列表，含当前品牌指标           |
| `GET /projects/{id}/overview`                   | 按搜索词聚合的分析数据，包含竞争对手提及   |
| `GET /projects/{id}/visibility?duration_days=7` | 每日可见度、情感分析和位置趋势        |
| `GET /projects/{id}/prompts`                    | 所有跟踪的搜索词，包含按 AI 服务商的指标 |
| `GET /projects/{id}/competitors`                | 检测到的竞争对手品牌及其指标         |
| `GET /projects/{id}/sources`                    | AI 服务商引用的域名，按引用次数排序    |

所有数据端点都需要 `X-API-Key` 请求头，并以 `{"success": true, "data": {...}}` 格式返回响应。

<Tip>
  要为用户提供快速摘要，请先调用 `GET /projects` 获取品牌的整体可见度评分和情感分析，然后调用 `GET /projects/{id}/overview` 获取按搜索词的细分。
</Tip>

***

## 完整工作流示例

用户提供或明确授权账户邮箱后，整个设置即可端到端运行。不要生成临时身份。第 2 步创建的 API 密钥是由管理员创建、对整个团队拥有完整权限的凭证。

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    # 1. Create an account
    curl -X POST "https://topify-customer-api-production.up.railway.app/api/public/v1/account/create" \
      -H "Content-Type: application/json" \
      -d '{"email": "user@example.com"}'

    # 2. Get an API key (use the password from step 1)
    curl -X POST "https://topify-customer-api-production.up.railway.app/api/public/v1/account/api-key" \
      -H "Content-Type: application/json" \
      -d '{"email": "user@example.com", "password": "Tp..."}'

    # 3. Create a project (use the API key from step 2)
    curl -X POST "https://topify-customer-api-production.up.railway.app/api/public/v1/account/projects" \
      -H "Content-Type: application/json" \
      -H "X-API-Key: tk_live_..." \
      -d '{
        "brand_name": "Acme Corp",
        "brand_url": "https://acme.com",
        "webhook_url": "https://your-service.com/webhooks/topify"
      }'

    # 4. Query project data after webhook confirms completion
    curl "https://topify-customer-api-production.up.railway.app/api/public/v1/projects" \
      -H "X-API-Key: tk_live_..."
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import httpx

    BASE = "https://topify-customer-api-production.up.railway.app/api/public/v1"

    # 1. Create account
    resp = httpx.post(f"{BASE}/account/create", json={
        "email": "user@example.com",
    })
    account = resp.json()["data"]
    password = account["password"]

    # 2. Get API key
    resp = httpx.post(f"{BASE}/account/api-key", json={
        "email": "user@example.com",
        "password": password,
    })
    api_key = resp.json()["data"]["api_key"]

    # 3. Create project
    headers = {"X-API-Key": api_key}
    resp = httpx.post(f"{BASE}/account/projects", json={
        "brand_name": "Acme Corp",
        "brand_url": "https://acme.com",
        "webhook_url": "https://your-service.com/webhooks/topify",
    }, headers=headers)
    project_id = resp.json()["data"]["project_id"]
    print(f"Project {project_id} is bootstrapping...")

    # 4. After webhook confirms completion, query data
    resp = httpx.get(f"{BASE}/projects", headers=headers)
    print(resp.json())
    ```
  </Tab>

  <Tab title="Node.js（服务端）">
    ```javascript theme={null}
    const BASE = "https://topify-customer-api-production.up.railway.app/api/public/v1";

    // 1. Create account
    let resp = await fetch(`${BASE}/account/create`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email: "user@example.com" }),
    });
    const { data: account } = await resp.json();

    // 2. Get API key
    resp = await fetch(`${BASE}/account/api-key`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        email: "user@example.com",
        password: account.password,
      }),
    });
    const { data: keyData } = await resp.json();

    // 3. Create project
    const headers = {
      "Content-Type": "application/json",
      "X-API-Key": keyData.api_key,
    };
    resp = await fetch(`${BASE}/account/projects`, {
      method: "POST",
      headers,
      body: JSON.stringify({
        brand_name: "Acme Corp",
        brand_url: "https://acme.com",
        webhook_url: "https://your-service.com/webhooks/topify",
      }),
    });
    const { data: project } = await resp.json();
    console.log(`Project ${project.project_id} is bootstrapping...`);

    // 4. After webhook confirms completion, query data
    resp = await fetch(`${BASE}/projects`, { headers });
    console.log(await resp.json());
    ```
  </Tab>
</Tabs>
