459 lines
9.7 KiB
Markdown
459 lines
9.7 KiB
Markdown
|
|
# 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 项目
|