# Cursor 官方用量接口文档

> 来源：Vibeviewer 项目逆向分析

## 基础配置

| 配置项 | 值 |
|--------|-----|
| Base URL | `https://cursor.com` |
| 认证方式 | Cookie Header |

### 通用 Headers

```http
accept: */*
content-type: application/json
origin: https://cursor.com
referer: https://cursor.com/dashboard
Cookie: <用户登录后的Cookie>
```

---

## API 接口

### 1. 获取用户信息

```
GET /api/dashboard/get-me
```

**请求参数**: 无 (仅需 Cookie)

**响应示例**:
```json
{
  "authId": "auth_xxxxx",
  "userId": 12345,
  "email": "user@example.com",
  "workosId": "workos_xxxxx",
  "teamId": 67890,
  "isEnterpriseUser": false
}
```

**字段说明**:
| 字段 | 类型 | 说明 |
|------|------|------|
| authId | String | 认证 ID |
| userId | Int | 用户 ID |
| email | String | 用户邮箱 |
| workosId | String | WorkOS ID |
| teamId | Int? | 团队 ID (个人用户为 null) |
| isEnterpriseUser | Bool | 是否企业用户 |

---

### 2. 获取用量摘要

```
GET /api/usage-summary
```

**请求参数**: 无 (仅需 Cookie)

**响应示例**:
```json
{
  "billingCycleStart": "2024-01-01T00:00:00.000Z",
  "billingCycleEnd": "2024-02-01T00:00:00.000Z",
  "membershipType": "pro",
  "limitType": "usage_based",
  "individualUsage": {
    "plan": {
      "used": 150,
      "limit": 500,
      "remaining": 350,
      "breakdown": {
        "included": 500,
        "bonus": 0,
        "total": 500
      }
    },
    "onDemand": {
      "used": 0,
      "limit": null,
      "remaining": null,
      "enabled": false
    }
  },
  "teamUsage": {
    "onDemand": {
      "used": 0,
      "limit": 10000,
      "remaining": 10000,
      "enabled": true
    }
  }
}
```

**会员类型 (membershipType)**:
| 值 | 说明 | 订阅名称 | 模型 | 套餐额度 |
|----|------|----------|------|---------|
| `free` | 免费版 | `free` | `default` | ~0 |
| `free_trial` | **Pro 试用** | `pro-free-trial` | `gpt-5.2-high` | 1000 |
| `pro` | Pro 会员 | `pro` | 高级模型 | 更高 |
| `business` | 商业版 | `business` | 企业级 | 无限 |

**重要**: `free_trial` 是 Pro 试用账号，拥有完整 Pro 功能，只是有时间限制！

**free_trial 特点**:
- `customSubscriptionName`: `pro-free-trial`
- 可用模型: `gpt-5.2-high` 等高级模型
- 套餐额度: 1000 (与 Pro 相同)
- 计费周期: 7天试用期
- `daysRemainingOnTrial`: 试用剩余天数

---

### 3. 获取当前计费周期

```
POST /api/dashboard/get-current-billing-cycle
```

**请求体**:
```json
{}
```

**响应示例**:
```json
{
  "startDateEpochMillis": "1704067200000",
  "endDateEpochMillis": "1706745600000"
}
```

**字段说明**:
| 字段 | 类型 | 说明 |
|------|------|------|
| startDateEpochMillis | String | 计费周期开始时间 (毫秒时间戳) |
| endDateEpochMillis | String | 计费周期结束时间 (毫秒时间戳) |

---

### 4. 获取过滤后的使用事件

```
POST /api/dashboard/get-filtered-usage-events
```

**请求体**:
```json
{
  "startDate": "1704067200000",
  "endDate": "1706745600000",
  "userId": 12345,
  "page": 1,
  "pageSize": 100
}
```

**请求参数说明**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| startDate | String | 是 | 开始时间 (毫秒时间戳字符串) |
| endDate | String | 是 | 结束时间 (毫秒时间戳字符串) |
| userId | Int | 是 | 用户 ID |
| page | Int | 是 | 页码 (从 1 开始) |
| pageSize | Int | 是 | 每页数量 (建议 100) |

**响应示例**:
```json
{
  "totalUsageEventsCount": 256,
  "usageEventsDisplay": [
    {
      "timestamp": "1704500000000",
      "model": "gpt-4",
      "kind": "chat",
      "requestsCosts": 0.05,
      "usageBasedCosts": "$0.05",
      "isTokenBasedCall": true,
      "owningUser": "user@example.com",
      "cursorTokenFee": 0.0,
      "tokenUsage": {
        "inputTokens": 1500,
        "outputTokens": 800,
        "totalCents": 5.0,
        "cacheWriteTokens": 0,
        "cacheReadTokens": 200
      }
    }
  ]
}
```

**事件字段说明**:
| 字段 | 类型 | 说明 |
|------|------|------|
| timestamp | String | 事件时间 (毫秒时间戳) |
| model | String | 使用的模型名称 |
| kind | String | 请求类型 (chat/completion 等) |
| requestsCosts | Double? | 请求费用 |
| usageBasedCosts | String | 费用显示字符串 (如 "$0.05") |
| isTokenBasedCall | Bool | 是否按 Token 计费 |
| owningUser | String | 用户邮箱 |
| cursorTokenFee | Double | Cursor Token 费用 |
| tokenUsage | Object | Token 使用详情 |

**tokenUsage 字段**:
| 字段 | 类型 | 说明 |
|------|------|------|
| inputTokens | Int? | 输入 Token 数 |
| outputTokens | Int? | 输出 Token 数 |
| totalCents | Double? | 总费用 (美分) |
| cacheWriteTokens | Int? | 缓存写入 Token 数 |
| cacheReadTokens | Int? | 缓存读取 Token 数 |

---

### 5. 获取聚合使用事件

```
POST /api/dashboard/get-aggregated-usage-events
```

**请求体**:
```json
{
  "teamId": 67890,
  "startDate": 1704067200000
}
```

**请求参数说明**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| teamId | Int? | 否 | 团队 ID (Pro 个人账号传 null) |
| startDate | Int64 | 是 | 开始时间 (毫秒时间戳，数字类型) |

**响应示例**:
```json
{
  "aggregations": [
    {
      "modelIntent": "gpt-4",
      "inputTokens": "150000",
      "outputTokens": "75000",
      "cacheWriteTokens": "0",
      "cacheReadTokens": "5000",
      "totalCents": 250.5
    },
    {
      "modelIntent": "claude-3-sonnet",
      "inputTokens": "80000",
      "outputTokens": "40000",
      "cacheWriteTokens": "0",
      "cacheReadTokens": "2000",
      "totalCents": 120.0
    }
  ],
  "totalInputTokens": "230000",
  "totalOutputTokens": "115000",
  "totalCacheWriteTokens": "0",
  "totalCacheReadTokens": "7000",
  "totalCostCents": 370.5
}
```

**聚合字段说明**:
| 字段 | 类型 | 说明 |
|------|------|------|
| modelIntent | String | 模型名称 |
| inputTokens | String | 输入 Token 总数 |
| outputTokens | String | 输出 Token 总数 |
| cacheWriteTokens | String | 缓存写入 Token 总数 |
| cacheReadTokens | String | 缓存读取 Token 总数 |
| totalCents | Double | 该模型总费用 (美分) |

---

## 重要字段说明

### totalUsageEventsCount (总请求次数)

这个字段在 `get-filtered-usage-events` 接口返回，表示计费周期内的**总请求/对话次数**。

```json
{
  "totalUsageEventsCount": 6,  // 总请求次数
  "usageEventsDisplay": [...]
}
```

**用途**:
- 统计用户使用频率
- 计费系统中的请求次数限制
- 账号活跃度判断

---

### 6. 获取团队成员消费 (Team Plan)

```
POST /api/dashboard/get-team-spend
```

**请求体**:
```json
{
  "teamId": 67890,
  "page": 1,
  "pageSize": 100,
  "sortBy": "name",
  "sortDirection": "asc"
}
```

**用途**: 获取团队各成员的消费情况，用于计算免费额度

---

### 7. 获取团队模型分析 (Team Plan)

```
POST /api/dashboard/get-team-models-analytics
```

**请求体**:
```json
{
  "startDate": "2024-01-01",
  "endDate": "2024-01-07",
  "c": "team_id"
}
```

**用途**: 获取团队模型使用分析数据

---

## 使用示例

### JavaScript/Node.js

```javascript
const axios = require('axios');

const cookie = 'your_cookie_here';

// 获取用户信息
async function getMe() {
  const res = await axios.get('https://cursor.com/api/dashboard/get-me', {
    headers: {
      'Cookie': cookie,
      'accept': '*/*',
      'referer': 'https://cursor.com/dashboard'
    }
  });
  return res.data;
}

// 获取用量摘要
async function getUsageSummary() {
  const res = await axios.get('https://cursor.com/api/usage-summary', {
    headers: {
      'Cookie': cookie,
      'accept': '*/*',
      'referer': 'https://cursor.com/dashboard?tab=usage'
    }
  });
  return res.data;
}

// 获取使用事件
async function getFilteredUsageEvents(userId, startDate, endDate, page = 1) {
  const res = await axios.post(
    'https://cursor.com/api/dashboard/get-filtered-usage-events',
    {
      startDate: startDate,
      endDate: endDate,
      userId: userId,
      page: page,
      pageSize: 100
    },
    {
      headers: {
        'Cookie': cookie,
        'Content-Type': 'application/json',
        'accept': '*/*',
        'origin': 'https://cursor.com',
        'referer': 'https://cursor.com/dashboard'
      }
    }
  );
  return res.data;
}
```

### Python

```python
import requests

cookie = 'your_cookie_here'
headers = {
    'Cookie': cookie,
    'accept': '*/*',
    'content-type': 'application/json',
    'origin': 'https://cursor.com',
    'referer': 'https://cursor.com/dashboard'
}

# 获取用户信息
def get_me():
    res = requests.get('https://cursor.com/api/dashboard/get-me', headers=headers)
    return res.json()

# 获取用量摘要
def get_usage_summary():
    res = requests.get('https://cursor.com/api/usage-summary', headers=headers)
    return res.json()

# 获取使用事件
def get_filtered_usage_events(user_id, start_date, end_date, page=1):
    data = {
        'startDate': start_date,
        'endDate': end_date,
        'userId': user_id,
        'page': page,
        'pageSize': 100
    }
    res = requests.post(
        'https://cursor.com/api/dashboard/get-filtered-usage-events',
        json=data,
        headers=headers
    )
    return res.json()
```

---

## 注意事项

1. **Cookie 获取**: 需要从浏览器登录 Cursor Dashboard 后获取 Cookie
2. **时间戳格式**: 大部分接口使用毫秒时间戳，注意区分字符串和数字类型
3. **分页**: `get-filtered-usage-events` 支持分页，每页最多 100 条
4. **账号类型**: 部分接口 (如 team-spend) 仅适用于团队账号
5. **费用单位**: `totalCents` 字段单位为美分，需除以 100 得到美元

---

## 更新日志

- 2024-12: 初始版本，来源 Vibeviewer 项目
