asana-apiAsana API integration with managed OAuth. Access tasks, projects, workspaces, users, and manage webhooks. Use this skill when users want to manage work items, track projects, or integrate with Asana workflows. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
Install via ClawdBot CLI:
clawdbot install byungkyu/asana-apiAccess the Asana API with managed OAuth authentication. Manage tasks, projects, workspaces, users, and webhooks for work management.
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
https://gateway.maton.ai/asana/{native-api-path}
Replace {native-api-path} with the actual Asana API endpoint path. The gateway proxies requests to app.asana.com and automatically injects your OAuth token.
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your Asana OAuth connections at https://ctrl.maton.ai.
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
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
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
Response:
{
"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": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
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
If you have multiple Asana connections, specify which one to use with the Maton-Connection header:
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
If omitted, the gateway uses the default (oldest) active connection.
GET /asana/api/1.0/tasks
Query parameters:
project - Project GID to filter tasksassignee - User GID or "me" for assigned tasksworkspace - Workspace GID (required if no project specified)completed_since - ISO 8601 date to filter tasks completed after this dateopt_fields - Comma-separated list of fields to includeExample:
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
Response:
{
"data": [
{
"gid": "1234567890",
"name": "Review quarterly report",
"completed": false,
"due_on": "2025-03-15"
}
]
}
GET /asana/api/1.0/tasks/{task_gid}
Example:
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
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"
}
}
Example:
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
PUT /asana/api/1.0/tasks/{task_gid}
Example:
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
DELETE /asana/api/1.0/tasks/{task_gid}
GET /asana/api/1.0/projects/{project_gid}/tasks
GET /asana/api/1.0/tasks/{task_gid}/subtasks
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"
}
}
Note: This endpoint requires an Asana Premium subscription.
GET /asana/api/1.0/workspaces/{workspace_gid}/tasks/search
Query parameters:
text - Text to search forassignee.any - Filter by assigneesprojects.any - Filter by projectscompleted - Filter by completion statusGET /asana/api/1.0/projects
Query parameters:
workspace - Workspace GIDteam - Team GIDopt_fields - Comma-separated list of fieldsExample:
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
Response:
{
"data": [
{
"gid": "1234567890",
"name": "Q1 Marketing Campaign",
"owner": {
"gid": "0987654321",
"name": "Alice Johnson"
},
"due_date": "2025-03-31"
}
]
}
GET /asana/api/1.0/projects/{project_gid}
POST /asana/api/1.0/projects
Example:
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
PUT /asana/api/1.0/projects/{project_gid}
DELETE /asana/api/1.0/projects/{project_gid}
GET /asana/api/1.0/workspaces
Example:
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
Response:
{
"data": [
{
"gid": "1234567890",
"name": "Acme Corp",
"is_organization": true
}
]
}
GET /asana/api/1.0/workspaces/{workspace_gid}
PUT /asana/api/1.0/workspaces/{workspace_gid}
POST /asana/api/1.0/workspaces/{workspace_gid}/addUser
POST /asana/api/1.0/workspaces/{workspace_gid}/removeUser
GET /asana/api/1.0/users
Query parameters:
workspace - Workspace GID to filter usersExample:
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
Response:
{
"data": [
{
"gid": "1234567890",
"name": "Alice Johnson",
"email": "alice.johnson@acme.com"
}
]
}
GET /asana/api/1.0/users/me
GET /asana/api/1.0/users/{user_gid}
GET /asana/api/1.0/teams/{team_gid}/users
GET /asana/api/1.0/workspaces/{workspace_gid}/users
GET /asana/api/1.0/webhooks
Query parameters:
workspace - Workspace GID (required)resource - Resource GID to filter byExample:
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
Note: Asana verifies the target URL is reachable and responds with a 200 status during webhook creation.
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"]
}
]
}
}
Example:
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
Response:
{
"data": {
"gid": "1234567890",
"resource": {
"gid": "1234567890",
"name": "Q1 Project"
},
"target": "https://example.com/webhook",
"active": true
}
}
GET /asana/api/1.0/webhooks/{webhook_gid}
PUT /asana/api/1.0/webhooks/{webhook_gid}
DELETE /asana/api/1.0/webhooks/{webhook_gid}
Returns 200 OK with empty data on success.
Asana uses cursor-based pagination. Use offset for pagination:
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
Response includes next_page when more results exist:
{
"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"
}
}
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();
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()
opt_fields to specify which fields to returncurl -g when URLs contain brackets (fields[], sort[], records[]) to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments. You may get "Invalid API key" errors when piping.| Status | Meaning |
|--------|---------|
| 400 | Bad request or missing Asana connection |
| 401 | Invalid or missing Maton API key |
| 403 | Forbidden - insufficient permissions |
| 404 | Resource not found |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Asana API |
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
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
asana. For example:https://gateway.maton.ai/asana/api/1.0/taskshttps://gateway.maton.ai/api/1.0/tasksGenerated Mar 1, 2026
Teams can use this skill to automate task assignments and progress tracking across distributed projects. It enables managers to fetch tasks by project or assignee, set due dates, and monitor completion status via API calls, streamlining coordination without manual updates.
Marketing agencies can integrate Asana with their tools to create and update tasks for campaign milestones automatically. By using the skill to manage tasks and webhooks, they ensure timely execution of content calendars and client deliverables, reducing manual oversight.
Product teams can sync Asana tasks with other development tools to track features and bugs. The skill allows fetching tasks by workspace or project, creating new tasks from external triggers, and updating statuses, keeping all stakeholders aligned on priorities and deadlines.
Service-based businesses can automate client onboarding by creating Asana tasks for each step, such as documentation and follow-ups. Using the skill to manage connections and tasks ensures consistent workflows, improves client satisfaction, and reduces administrative overhead.
Companies can offer this skill as part of a larger integration platform, charging subscription fees for access to managed OAuth and API gateway services. It attracts businesses needing seamless Asana connectivity without handling authentication complexities.
Consultants can use this skill to build custom Asana automations for clients, charging project-based or retainer fees. It enables them to deliver tailored solutions for task management and workflow optimization, leveraging the skill's API capabilities.
Developers can create a freemium tool that uses this skill to offer basic Asana integrations for free, with premium features like advanced analytics or multi-connection support. This model drives user adoption and upsells to paid plans.
💬 Integration Tip
Start by setting the MATON_API_KEY environment variable and testing with simple GET requests to fetch tasks, then expand to POST for creating tasks and managing connections via the control endpoints.
Use the mcporter CLI to list, configure, auth, and call MCP servers/tools directly (HTTP or stdio), including ad-hoc servers, config edits, and CLI/type generation.
Connect to 100+ APIs (Google Workspace, Microsoft 365, GitHub, Notion, Slack, Airtable, HubSpot, etc.) with managed OAuth. Use this skill when users want to...
Build, debug, and deploy websites using HTML, CSS, JavaScript, and modern frameworks following production best practices.
YouTube Data API integration with managed OAuth. Search videos, manage playlists, access channel data, and interact with comments. Use this skill when users want to interact with YouTube. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
Scaffold, test, document, and debug REST and GraphQL APIs. Use when the user needs to create API endpoints, write integration tests, generate OpenAPI specs, test with curl, mock APIs, or troubleshoot HTTP issues.
Search for jobs across LinkedIn, Indeed, Glassdoor, ZipRecruiter, Google Jobs, Bayt, Naukri, and BDJobs using the JobSpy MCP server.