介绍
# Asana
通过托管的 OAuth 身份验证访问 Asana API。管理工作管理的任务、项目、工作区、用户和 Webhook。
## 快速开始
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/tasks?project=PROJECT_GID') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
## 基础 URL
``` https://gateway.maton.ai/asana/{native-api-path} ```
将 `{native-api-path}` 替换为实际的 Asana API 端点路径。网关将请求代理到 `app.asana.com` 并自动注入您的 OAuth 令牌。
## 身份验证
所有请求都需要在 Authorization 标头中包含 Maton API 密钥:
``` Authorization: Bearer $MATON_API_KEY ```
**环境变量:** 将您的 API 密钥设置为 `MATON_API_KEY`:
```bash export MATON_API_KEY="YOUR_API_KEY" ```
### 获取您的 API 密钥
1. 登录或在 [maton.ai](https://maton.ai) 创建账户 2. 前往 [maton.ai/settings](https://maton.ai/settings) 3. 复制您的 API 密钥
## 连接管理
在 `https://ctrl.maton.ai` 管理您的 Asana OAuth 连接。
### 列出连接
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections?app=asana&status=ACTIVE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### 创建连接
```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'app': 'asana'}).encode() req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### 获取连接
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**响应:** ```json { "connection": { "connection_id": "21fd90f9-5935-43cd-b6c8-bde9d915ca80", "status": "ACTIVE", "creation_time": "2025-12-08T07:20:53.488460Z", "last_updated_time": "2026-01-31T20:03:32.593153Z", "url": "https://connect.maton.ai/?session_token=...", "app": "asana", "metadata": {} } } ```
在浏览器中打开返回的 `url` 以完成 OAuth 授权。
### 删除连接
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### 指定连接
如果您有多个 Asana 连接,请使用 `Maton-Connection` 标头指定要使用的连接:
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/tasks?project=PROJECT_GID') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Maton-Connection', '21fd90f9-5935-43cd-b6c8-bde9d915ca80') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
如果省略,网关将使用默认(最旧的)活动连接。
## API 参考
### 任务 (Tasks)
#### 获取多个任务
```bash GET /asana/api/1.0/tasks ```
查询参数: - `project` - 用于过滤任务的项目 GID - `assignee` - 用户 GID 或 "me",表示已分配的任务 - `workspace` - 工作区 GID(如果未指定项目,则为必填) - `completed_since` - ISO 8601 日期,用于过滤在此日期之后完成的任务 - `opt_fields` - 要包含的字段的逗号分隔列表
**示例:**
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/tasks?project=1234567890&opt_fields=name,completed,due_on') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**响应:** ```json { "data": [ { "gid": "1234567890", "name": "Review quarterly report", "completed": false, "due_on": "2025-03-15" } ] } ```
#### 获取单个任务
```bash GET /asana/api/1.0/tasks/{task_gid} ```
**示例:**
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/tasks/1234567890') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### 创建任务
```bash POST /asana/api/1.0/tasks Content-Type: application/json
{ "data": { "name": "New task", "projects": ["PROJECT_GID"], "assignee": "USER_GID", "due_on": "2025-03-20", "notes": "Task description here" } } ```
**示例:**
```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'name': 'Complete API integration', 'projects': ['1234567890'], 'due_on': '2025-03-20'}}).encode() req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/tasks', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### 更新任务
```bash PUT /asana/api/1.0/tasks/{task_gid} ```
**示例:**
```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'completed': True}}).encode() req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/tasks/1234567890', data=data, method='PUT') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### 删除任务
```bash DELETE /asana/api/1.0/tasks/{task_gid} ```
#### 从项目获取任务
```bash GET /asana/api/1.0/projects/{project_gid}/tasks ```
#### 获取子任务
```bash GET /asana/api/1.0/tasks/{task_gid}/subtasks ```
#### 创建子任务
```bash POST /asana/api/1.0/tasks/{task_gid}/subtasks Content-Type: application/json
{ "data": { "name": "Subtask name", "assignee": "USER_GID", "due_on": "2025-03-20" } } ```
#### 搜索任务 (Premium)
**注意:** 此端点需要 Asana Premium 订阅。
```bash GET /asana/api/1.0/workspaces/{workspace_gid}/tasks/search ```
查询参数: - `text` - 要搜索的文本 - `assignee.any` - 按指派人过滤 - `projects.any` - 按项目过滤 - `completed` - 按完成状态过滤
### 项目 (Projects)
#### 获取多个项目
```bash GET /asana/api/1.0/projects ```
查询参数: - `workspace` - 工作区 GID - `team` - 团队 GID - `opt_fields` - 字段的逗号分隔列表
**示例:**
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/projects?workspace=1234567890&opt_fields=name,owner,due_date') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**响应:** ```json { "data": [ { "gid": "1234567890", "name": "Q1 Marketing Campaign", "owner": { "gid": "0987654321", "name": "Alice Johnson" }, "due_date": "2025-03-31" } ] } ```
#### 获取单个项目
```bash GET /asana/api/1.0/projects/{project_gid} ```
#### 创建项目
```bash POST /asana/api/1.0/projects ```
**示例:**
```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'name': 'New Project', 'workspace': '1234567890', 'notes': 'Project description'}}).encode() req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/projects', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### 更新项目
```bash PUT /asana/api/1.0/projects/{project_gid} ```
#### 删除项目
```bash DELETE /asana/api/1.0/projects/{project_gid} ```
### 工作区 (Workspaces)
#### 获取多个工作区
```bash GET /asana/api/1.0/workspaces ```
**示例:**
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/workspaces') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**响应:** ```json { "data": [ { "gid": "1234567890", "name": "Acme Corp", "is_organization": true } ] } ```
#### 获取单个工作区
```bash GET /asana/api/1.0/workspaces/{workspace_gid} ```
#### 更新工作区
```bash PUT /asana/api/1.0/workspaces/{workspace_gid} ```
#### 向工作区添加用户
```bash POST /asana/api/1.0/workspaces/{workspace_gid}/addUser ```
#### 从工作区移除用户
```bash POST /asana/api/1.0/workspaces/{workspace_gid}/removeUser ```
### 用户 (Users)
#### 获取多个用户
```bash GET /asana/api/1.0/users ```
查询参数: - `workspace` - 用于过滤用户的工作区 GID
**示例:**
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/users?workspace=1234567890&opt_fields=name,email') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**响应:** ```json { "data": [ { "gid": "1234567890", "name": "Alice Johnson", "email": "[email protected]" } ] } ```
#### 获取当前用户
```bash GET /asana/api/1.0/users/me ```
#### 获取单个用户
```bash GET /asana/api/1.0/users/{user_gid} ```
#### 获取团队中的用户
```bash GET /asana/api/1.0/teams/{team_gid}/users ```
#### 获取工作区中的用户
```bash GET /asana/api/1.0/workspaces/{workspace_gid}/users ```
### Webhooks
#### 获取多个 Webhooks
```bash GET /asana/api/1.0/webhooks ```
查询参数: - `workspace` - 工作区 GID(必填) - `resource` - 用于过滤的资源 GID
**示例:**
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/webhooks?workspace=1234567890') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### 创建 Webhook
**注意:** Asana 会在创建 Webhook 期间验证目标 URL 是否可访问并响应 200 状态码。
```bash POST /asana/api/1.0/webhooks Content-Type: application/json
{ "data": { "resource": "PROJECT_OR_TASK_GID", "target": "https://example.com/webhook", "filters": [ { "resource_type": "task", "action": "changed", "fields": ["completed", "due_on"] } ] } } ```
**示例:**
```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'resource': '1234567890', 'target': 'https://example.com/webhook'}}).encode() req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/webhooks', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**响应:** ```json { "data": { "gid": "1234567890", "resource": { "gid": "1234567890", "name": "Q1 Project" }, "target": "https://example.com/webhook", "active": true } } ```
#### 获取单个 Webhook
```bash GET /asana/api/1.0/webhooks/{webhook_gid} ```
#### 更新 Webhook
```bash PUT /asana/api/1.0/webhooks/{webhook_gid} ```
#### 删除 Webhook
```bash DELETE /asana/api/1.0/webhooks/{webhook_gid} ```
成功时返回 `200 OK` 且包含空数据。
## 分页
Asana 使用基于游标的分页。使用 `offset` 进行分页:
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/asana/api/1.0/tasks?project=1234567890&limit=50&offset=OFFSET_TOKEN') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
当存在更多结果时,响应包含 `next_page`:
```json { "data": [...], "next_page": { "offset": "eyJ0eXBlIjoib2Zmc2V0IiwidmFsdWUiOjUwfQ", "path": "/tasks?project=1234567890&limit=50&offset=eyJ0eXBlIjoib2Zmc2V0IiwidmFsdWUiOjUwfQ", "uri": "https://app.asana.com/api/1.0/tasks?project=1234567890&limit=50&offset=eyJ0eXBlIjoib2Zmc2V0IiwidmFsdWUiOjUwfQ" } } ```
## 代码示例
### JavaScript
```javascript const response = await fetch( 'https://gateway.maton.ai/asana/api/1.0/tasks?project=1234567890', { headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}` } } ); const data = await response.json(); ```
### Python
```python import os import requests
response = requests.get( 'https://gateway.maton.ai/asana/api/1.0/tasks', headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}, params={'project': '1234567890'} ) data = response.json() ```
## 注意事项
- 资源 ID (GID) 是字符串 - 时间戳采用 ISO 8601 格式 - 使用 `opt_fields` 指定要返回的字段 - 工作区是最高级别的组织单位 - 组织是代表公司的专用工作区 - 重要:使用 curl 命令时,如果 URL 包含括号(`fields[]`、`sort[]`、`records[]`),请使用 `curl -g` 以禁用 glob 解析 - 重要:当将 curl 输出通过管道传递给 `jq` 或其他命令时,在某些 shell 环境中,`$MATON_API_KEY` 等环境变量可能无法正确展开。通过管道传输时,您可能会遇到“Invalid API key”(API 密钥无效)错误。
## 错误处理
| 状态 | 含义 | |--------|---------| | 400 | 错误的请求或缺少 Asana 连接 | | 401 | 无效或缺少 Maton API 密钥 | | 403 | 禁止访问 - 权限不足 | | 404 | 资源未找到 | | 429 | 速率受限 | | 4xx/5xx | 来自 Asana API 的透传错误 |
### 故障排除:API 密钥问题
1. 检查是否设置了 `MATON_API_KEY` 环境变量:
```bash echo $MATON_API_KEY ```
2. 通过列出连接来验证 API 密钥是否有效:
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### 故障排除:应用名称无效
1. 确保您的 URL 路径以 `asana` 开头。例如:
- 正确:`https://gateway.maton.ai/asana/api/1.0/tasks` - 错误:`https://gateway.maton.ai/api/1.0/tasks`
## 资源
- [Asana API 文档](https://developers.asana.com) - [API 参考](https://developers.asana.com/reference) - [LLM 参考](https://developers.asana.com/llms.txt) - [Maton 社区](https://discord.com/invite/dBfFAcefs2) - [Maton 支持](mailto:[email protected])