Getting Started

Action API Guide

11 min readStart here

The Public API v2 is an action-based API. Each operation sends a JSON body with POST to a named endpoint.

It is not RESTful. It has no GET /workspaces or PUT /tasks/{id} routes.

Media downloads, bundle downloads, and webhook registration are the REST-style exceptions.


v2 is in beta (2.0.0-beta) and runs alongside v1. It adds promptAgent and signed webhook registration.

Tasks are fully writable in v2 as of August 2026. The API includes createTask, updateTask, deleteTask, and moveTask.

It also includes complete and uncomplete operations, assignees, dates, notes, and custom fields.

v1 has the longest track record. It alone provides single-task read endpoints such as GET /tasks/{taskId}.

Neither version can rename a project. See Which API should I use?.

The live OpenAPI spec is published at taskade.com/api/documentation/v2.

Table of Contents


Which API should I use?

Taskade ships two public HTTP APIs. They share the same authentication.

REST API v1 Action API v2
Base URL https://www.taskade.com/api/v1 https://www.taskade.com/api/v2
Style RESTful (GET/POST/PUT/DELETE) Action / RPC (POST /{operation})
Status Stable (GA) Beta (2.0.0-beta)
Live spec /api/documentation/v1 /api/documentation/v2
Task create / update / delete ✅ Full CRUD ✅ Full CRUD (createTask, updateTask, deleteTask, moveTask)
Task assignees / dates / notes / fields ✅ (assignTask, setTaskDate, setTaskNote, setTaskFieldValue, …)
Read a single task, date, note or field GET /tasks/{taskId} etc. ❌ list-only (listTasks, listBlocks, listFields)
Project update / rename ❌ (create / complete / restore / copy only)
Prompt an agent promptAgent
Agent lifecycle (create/update/delete)
Bundles (export/import Taskade Genesis apps)
Signed webhook registration POST /webhooks
Reference API reference This page

Use v2 for LLM tools, agent prompts, or webhook registration. One verb per endpoint maps directly to a tool definition.

Use v1 for its longer stability record. Also use v1 to read one task, date, note, or field directly.

Every row above is checkable: it is derived from the two live OpenAPI documents, and the generated Action API reference and REST API reference are built from those same specs.


Base URL & Authentication

All v2 operations live under:

https://www.taskade.com/api/v2

Authenticate with a Personal Access Token from taskade.com/settings/api, or an OAuth 2.0 access token for apps that act on behalf of other users:

Bash
Authorization: Bearer YOUR_TOKEN

See the Authentication guide for personal tokens vs. OAuth 2.0 (PKCE) details.


Calling convention

Every v2 call sends a JSON body with POST to an operation name. The API returns JSON.

Successful responses use { "ok": true, ... }.

Here is a single Action API v2 call, from authentication to JSON response.

Bash
curl -X POST https://www.taskade.com/api/v2/OPERATION \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "param": "value" }'

A typical response:

Json
{ "ok": true, "items": [ /* ... */ ] }


Receiving events: Register a signed outbound webhook with POST /api/v2/webhooks (Pro and above).

Taskade signs every delivery with an HMAC secret. Make sure that each signature is valid.

See the Webhook Registration API. The older subscribeWebhook and unsubscribeWebhook operations are deprecated.


Endpoints

List spaces (workspaces)

POST /listSpaces is every integration's entry point. Body is optional.

cURL
Bash
curl -X POST https://www.taskade.com/api/v2/listSpaces \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
Python
Python
import requests

res = requests.post(
    "https://www.taskade.com/api/v2/listSpaces",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    json={},
)
print(res.json()["items"])
TypeScript
Typescript
const res = await fetch("https://www.taskade.com/api/v2/listSpaces", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TASKADE_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const { items } = await res.json();

Filter with { "filterBy": { "name": { "operator": "contains", "value": "Marketing" } } }.


List folders in a space

POST /listFolders

Bash
curl -X POST https://www.taskade.com/api/v2/listFolders \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "spaceId": "SPACE_ID" }'

List projects in a space

POST /listProjects

Bash
curl -X POST https://www.taskade.com/api/v2/listProjects \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "spaceId": "SPACE_ID" }'

Get a project

POST /getProject returns { ok, item: { id, name } }.

Bash
curl -X POST https://www.taskade.com/api/v2/getProject \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "projectId": "PROJECT_ID" }'

Create a project

POST /createProject seeds a project from Markdown.

cURL
Bash
curl -X POST https://www.taskade.com/api/v2/createProject \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "spaceId": "SPACE_ID",
    "contentType": "text/markdown",
    "content": "# Q2 Planning\n\n- Review roadmap\n- Draft OKRs"
  }'
Python
Python
import requests

res = requests.post(
    "https://www.taskade.com/api/v2/createProject",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    json={
        "spaceId": "SPACE_ID",
        "contentType": "text/markdown",
        "content": "# Q2 Planning\n\n- Review roadmap\n- Draft OKRs",
    },
)
print(res.json()["item"]["id"])

List tasks

POST /listTasks is paginated with after / before cursors. Each task is { id, text, parentId?, completed }.

Bash
curl -X POST https://www.taskade.com/api/v2/listTasks \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "projectId": "PROJECT_ID", "limit": 100 }'


To create, update, complete, or delete tasks, or to set assignees, dates, notes, and custom fields, v2 has you covered: see createTask, updateTask, moveTask, assignTask, setTaskDate, setTaskNote, and setTaskFieldValue. To read one task rather than listing a project, use the REST API v1 Tasks endpoints.

If Google Calendar is connected on an eligible workspace, dates set with setTaskDate can sync the same way as dates set in Taskade.


Prompt an agent

POST /promptAgent sends a single prompt to a workspace agent and returns a synchronous text response. This capability is v2-only.

cURL
Bash
curl -X POST https://www.taskade.com/api/v2/promptAgent \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "spaceId": "SPACE_ID",
    "agentId": "AGENT_ID",
    "prompt": "Summarize yesterday'\''s standup notes"
  }'
Python
Python
import requests

res = requests.post(
    "https://www.taskade.com/api/v2/promptAgent",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    json={
        "spaceId": "SPACE_ID",
        "agentId": "AGENT_ID",
        "prompt": "Summarize yesterday's standup notes",
    },
)
print(res.json()["summary"])
TypeScript
Typescript
const res = await fetch("https://www.taskade.com/api/v2/promptAgent", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TASKADE_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ spaceId, agentId, prompt: "Summarize standup notes" }),
});
const { summary } = await res.json();

Response:

Json
{ "ok": true, "summary": "Here's a summary of the standup..." }

To review past conversations, use POST /listConversations ({ agentId, limit?, page? }) and POST /getConversation ({ agentId, convoId, includeTranscript? }). Pass "includeTranscript": true to get a Markdown transcript of the conversation in the response.


Manage agents

Operation Body
POST /listAgents { spaceId, filterBy? }
POST /getAgent { agentId }
POST /createAgent { folderId, name, data }
POST /updateAgent { agentId, name?, data? }
POST /deleteAgent { agentId }
POST /generateAgent { folderId, text } — generate an agent from a description
POST /enablePublicAgentAccess { agentId }{ ok, publicUrl }

Attach knowledge to an agent

POST /addKnowledgeProject grounds an agent in a project. (removeKnowledgeProject, addKnowledgeMedia, removeKnowledgeMedia mirror it.)

Bash
curl -X POST https://www.taskade.com/api/v2/addKnowledgeProject \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "agentId": "AGENT_ID", "projectId": "PROJECT_ID" }'

Export / import a bundle

POST /exportBundle returns a portable Genesis app bundle. POST /importBundle installs one.

See Bundles & App Kits for the full schema and binary .tsk variants.

Bash
curl -X POST https://www.taskade.com/api/v2/exportBundle \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "spaceId": "SPACE_ID" }'

Full operation list

  • Workspaces & structure: listSpaces, listFolders, listMyProjects, listTemplates, listMedia.
  • Projects: listProjects, getProject, createProject, createProjectFromTemplate, copyProject, completeProject, restoreProject, listTasks, listBlocks, listFields, listProjectMembers, getShareLink, enableShareLink.
  • Agents: listAgents, getAgent, createAgent, updateAgent, deleteAgent, promptAgent, generateAgent, listConversations, getConversation, addKnowledgeProject, removeKnowledgeProject, addKnowledgeMedia, removeKnowledgeMedia, enablePublicAgentAccess, getPublicAgent, updatePublicAgent.
  • Media: uploadMedia, getMedia, deleteMedia, plus GET /media/{mediaId}/content and GET /media/spaces/{spaceId}/content for downloads.
  • Bundles: exportBundle, importBundle, importBundleZip, plus GET /bundles/{spaceId}/export/zip.
  • Webhooks: POST /webhooks, GET /webhooks, GET /webhooks/{id}, DELETE /webhooks/{id}. See Webhooks. subscribeWebhook and unsubscribeWebhook are deprecated.

The authoritative, always-current list is the live v2 spec.


Pagination

List operations that can return many rows use cursor pagination with after / before (tasks, blocks) or page / limit (members, conversations).

Bash
# next page of tasks
curl -X POST https://www.taskade.com/api/v2/listTasks \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "projectId": "PROJECT_ID", "limit": 100, "after": "LAST_TASK_ID" }'

Rate Limits

Requests are rate-limited per endpoint. Taskade does not publish exact ceilings, and the ceilings can change.

If you receive 429, use these response headers:

Header Meaning
x-rate-limit-limit Your total budget for the current window
x-rate-limit-remaining Requests left in the window (0 when you are blocked)
x-rate-limit-reset Seconds until the window reopens — schedule your retry from this

Taskade does not send Retry-After. Wait for x-rate-limit-reset before you retry. Earlier retries are also rejected.

Typescript
async function withRetry<T>(fn: () => Promise<T>, retries = 3): Promise<T> {
  for (let i = 0; i < retries; i++) {
    try {
      return await fn();
    } catch (err: any) {
      if (err.status === 429 && i < retries - 1) {
        const resetSec = Number(err.headers?.["x-rate-limit-reset"]);
        const waitMs = resetSec > 0 ? resetSec * 1000 : 2 ** i * 1000;
        await new Promise(r => setTimeout(r, waitMs));
        continue;
      }
      throw err;
    }
  }
  throw new Error("Retry exhausted");
}

For sustained throughput, batch operations such as /createTask, which accepts arrays. Reduce polling frequency. Stagger scheduled jobs.


Error Handling

All error responses share this shape:

Json
{
  "ok": false,
  "message": "Project not found",
  "code": "not_found",
  "statusMessage": "Not Found"
}
Status Meaning Retry? Fix
400 Bad request No Examine the request body
401 Invalid / missing token No Regenerate or refresh the token
402 Out of credits, or the operation needs a higher plan (e.g. webhook registration requires Pro) No Top up credits or upgrade your plan
403 Insufficient permission No Use a token with access to the resource
404 Not found No Make sure that the ID and workspace access are correct
429 Rate limited Yes Exponential backoff
5xx Server error Yes Retry up to 3 times with backoff


Never retry on 400, 401, 403, or 404. Fix the request first.


Security Best Practices

  • Never commit tokens. Use environment variables or a secret manager.
  • Use OAuth, not personal tokens, for multi-user applications.
  • Rotate personal tokens periodically. You can hold up to 5 at a time.
  • Encrypt refresh tokens at rest. They are long-lived.

REST API Guide

Authentication

Webhooks

Bundles & App Kits