{
 "slug": "todoist",
 "name": "Todoist",
 "url": "https://todoist.com",
 "domain": "todoist.com",
 "category": "task-management",
 "category_name": "Task management",
 "tested_at": "2026-10-06",
 "run": "20261006T093911Z",
 "draft": false,
 "reviewed": true,
 "owner_verified": null,
 "origin": "editorial",
 "history": [
  {
   "run": "20261001T212054Z",
   "date": "2026-10-01",
   "level": 1,
   "engine": {
    "runner": "omp",
    "model": null,
    "driver": null,
    "signed": true,
    "inbox": [
     "agentdrives.com"
    ],
    "robots": "start"
   },
   "drives": 3
  },
  {
   "run": "20261006T093911Z",
   "date": "2026-10-06",
   "level": 1,
   "engine": {
    "runner": "omp",
    "model": "claude-opus-5-5",
    "driver": 2,
    "signed": true,
    "inbox": [
     "agentdrives.com"
    ],
    "robots": "start"
   }
  }
 ],
 "level": 1,
 "level_name": "Needs a person",
 "level_selfhost": null,
 "entry": "closed",
 "door": {
  "passed": 0,
  "tries": 3,
  "self_start": false
 },
 "badges": [],
 "stages": [
  {
   "key": "in",
   "label": "Access",
   "state": "no",
   "text": "Can't get in on its own",
   "at": "signup"
  },
  {
   "key": "work",
   "label": "Use",
   "state": "unreached",
   "text": "Work not measured"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "unreached",
   "text": "Payment not reached",
   "value": "unreached",
   "route": "card_checkout"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "unreached",
   "text": "Leaving not reached",
   "how": "no-account"
  }
 ],
 "outcomes": [
  {
   "key": "find",
   "label": "Find",
   "state": "part",
   "text": "Some docs agents can read: an OpenAPI and an MCP server",
   "have": [
    "openapi",
    "mcp"
   ]
  },
  {
   "key": "access",
   "label": "Access",
   "state": "no",
   "text": "Can't get in on its own",
   "at": "signup",
   "stage": "in"
  },
  {
   "key": "use",
   "label": "Use",
   "state": "unreached",
   "text": "Work not measured",
   "stage": "work"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "unreached",
   "text": "Payment not reached",
   "value": "unreached",
   "route": "card_checkout",
   "stage": "pay"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "unreached",
   "text": "Leaving not reached",
   "how": "no-account",
   "stage": "leave"
  }
 ],
 "access": [
  {
   "key": "person",
   "label": "A person sets it up",
   "routes": [],
   "minutes": null,
   "core": null
  }
 ],
 "minutes": null,
 "next": {
  "to": 2,
  "text": "Next: let an agent sign up on its own"
 },
 "stop": "signup",
 "core": "0/10",
 "scores": {
  "coverage": null,
  "reliability": null,
  "resilience": null,
  "setup": 80,
  "surface_coverage": null,
  "docs_accuracy": null,
  "docs_completeness": null
 },
 "parts": {
  "holds_up": null,
  "docs_match": null,
  "setup": 80,
  "security": null,
  "standards": [
   {
    "standard": "MCP client registration",
    "state": "current",
    "behind": null,
    "value": "cimd"
   },
   {
    "standard": "OpenAPI",
    "state": "behind",
    "behind": 1,
    "value": "3.1.0"
   }
  ]
 },
 "reliability_method": null,
 "resilience": null,
 "stress": [],
 "surface_audit": null,
 "coverage_core": null,
 "after_wall": null,
 "coverage_source": "computed",
 "driver": {
  "version": 2,
  "model": "claude-opus-5-5",
  "profile": "full",
  "assisted": false,
  "handoff": null,
  "prompt_sha": "f3d0adeeb256",
  "kb_version": "2+overlay-9e43028a2c",
  "identity": null
 },
 "methodology": 15,
 "rules_date": "2026-10-15",
 "engine": {
  "runner": "omp",
  "model": "claude-opus-5-5",
  "driver": 2,
  "signed": true,
  "inbox": [
   "agentdrives.com"
  ],
  "robots": "start"
 },
 "same_level_drives": 4,
 "drives": 4,
 "works_assisted": null,
 "freshness": "fresh",
 "nothing_to_pay": false,
 "core_gated": false,
 "profiles": {},
 "agent_check": {
  "rung": "signup",
  "vendor": "Cloudflare Turnstile (invisible)",
  "visible": false,
  "type": "network",
  "human": null,
  "how": "Let verified bots and signed agents past the check on sign-up: in Cloudflare, add a WAF custom rule that skips the bot challenge on your sign-up paths for verified bots and for signed agents (rule field cf.bot_management.signed_agent; since 1 July 2026 signed agents count as verified bots), and render Turnstile only when the request is not from a verified agent.",
  "signed": true
 },
 "agent_pass": null,
 "who_gets_in": {
  "server": {
   "state": "form"
  },
  "signed": {
   "state": "page",
   "kind": "signup",
   "at": "2026-10-13"
  },
  "browser": {
   "state": "through",
   "measured": false
  },
  "our_key": "pending",
  "robots": null,
  "tip": false
 },
 "ladder": {
  "docs": {
   "status": "headless",
   "note": "No llms.txt, no markdown version."
  },
  "signup": {
   "status": "blocked",
   "note": "No API sign-up. The email form at app.todoist.com/auth/signup runs an invisible Cloudflare Turnstile that rejected our agent's browser ('Captcha verification failed. Please try again.'), with no visible challenge shown. Other routes are Google, Facebook or Apple accounts only, which we have no account for."
  },
  "verify": {
   "status": "",
   "note": "Not reached: no account was created and no mail arrived.",
   "reached": false
  },
  "credentials": {
   "status": "",
   "note": "Dynamic client registration works headless (POST todoist.com/oauth/register 201), but every token path (OAuth code + PKCE, personal token in settings, td auth login) needs a logged-in account. No device flow, no agent registration. The AS refused resource=https://api.todoist.com (invalid_target), the value in the API's own PRM.",
   "via": "",
   "reached": false
  },
  "first_call": {
   "status": "",
   "note": "GET /api/v1/tasks answers 401 JSON with Retry-After; no token could be obtained.",
   "reached": false
  },
  "first_action": {
   "status": "",
   "note": "Not reached: no credentials.",
   "reached": false
  },
  "pay": {
   "status": "",
   "grade": "P2",
   "rails": [
    "Stripe Checkout (hosted)"
   ],
   "rail_ids": [
    "stripe-checkout"
   ],
   "first_party": false,
   "rail_scope": "none",
   "trial_path": "free tier",
   "note": "No 402, x402, MPP, UCP or registry listing found. The OpenAPI documents Stripe-hosted flows (usage_billing/top_up creates a hosted Stripe Checkout session; cancel_plan_with_redirect_to_stripe). The Pro upgrade checkout itself was not reached because no account could be created; from the docs only.",
   "reached": false
  },
  "cancel": {
   "status": "",
   "note": "No plan was started. Docs: POST /api/v1/payments/cancel_plan_with_redirect_to_stripe returns a URL for a hosted cancellation flow, so cancelling ends in a web page.",
   "docs_grade": "",
   "reached": false
  },
  "delete": {
   "status": "",
   "note": "No account was created, so there was nothing to delete. No account-deletion operation found in the API reference.",
   "account": false,
   "reached": false
  }
 },
 "routes": [],
 "checkout": null,
 "docs": null,
 "claims": null,
 "pay_options": {
  "checked": "2026-10-06",
  "source": "drive",
  "options": [
   {
    "id": "stripe-checkout",
    "name": "Stripe Checkout",
    "kind": "checkout",
    "first_party": false,
    "lead": false,
    "networks": [],
    "testnet": false
   }
  ],
  "agentic": [],
  "paid": null,
  "exercised": null,
  "detected_grade": null,
  "trial": {
   "no_card": null,
   "card_required": null,
   "free_plan": true
  },
  "owner_fixes": [
   {
    "title": "Accept x402 or MPP on your API",
    "how": "Answer an unpaid call with 402 and a payment challenge, so an agent pays per call or buys credits without an account or a card."
   },
   {
    "title": "List your plans on Stripe Projects",
    "how": "Agents buy a plan with `stripe projects add`, paid with a token under a spend cap the owner sets (projects.dev)."
   }
  ]
 },
 "surfaces": {
  "api": true,
  "openapi": true,
  "cli": true,
  "sdk": true,
  "mcp": "official",
  "llms_txt": false,
  "webhooks": true,
  "sandbox": false
 },
 "surface_notes": {
  "api": "REST v1 + Sync endpoint, 78 paths / 108 operations in the spec",
  "openapi": "3.1.0, embedded in the Redoc page; no standalone spec URL found",
  "mcp": "official hosted, https://ai.todoist.net/mcp, OAuth",
  "cli": "@doist/todoist-cli 5.4.5 (td), login via browser",
  "sdk": "TypeScript SDK (doist.github.io/todoist-sdk-typescript)"
 },
 "can_do": [
  "Read the full API reference and OpenAPI 3.1.0 spec without an account",
  "Discover the MCP server's OAuth setup (PRM, authorization server metadata) without an account",
  "Register an OAuth client headless through dynamic client registration"
 ],
 "cannot_do": [
  {
   "what": "Create a Todoist account",
   "why": "Invisible Cloudflare Turnstile on the email sign-up form rejected our agent's browser; no API sign-up"
  },
  {
   "what": "Get an API token or OAuth grant",
   "why": "All token routes need a logged-in account"
  },
  {
   "what": "Create, schedule or complete any task",
   "why": "No credentials"
  }
 ],
 "blockers": [
  "Invisible Cloudflare Turnstile on the email sign-up form rejects an automated browser"
 ],
 "tips_for_owner": [
  "Let signed agents through sign-up",
  "Add an agent-friendly sign-up route",
  "Offer the device flow for tokens",
  "Accept the API's own resource indicator",
  "Publish llms.txt and markdown docs"
 ],
 "tips_for_agents": [
  "You need a human to create the account: the email sign-up form runs an invisible Cloudflare Turnstile.",
  "Once an account exists, use the official MCP server https://ai.todoist.net/mcp (OAuth via todoist.com, CIMD or DCR) or the REST API v1 with a personal token from Settings > Integrations.",
  "Use resource=https://ai.todoist.net/mcp at /oauth/authorize; resource=https://api.todoist.com is refused with invalid_target.",
  "Failed unauthenticated calls raise Retry-After quickly (5 s to 129 s); do not loop on 401s."
 ],
 "selfhost": null,
 "summary": "Todoist has a strong agent surface on paper: an OpenAPI 3.1.0 REST API, an official OAuth MCP server with PRM and CIMD/DCR, a CLI and SDK. But an agent cannot get in on its own: the email sign-up form runs an invisible Cloudflare Turnstile that rejected our agent's browser to complete it, so no account, token or capability could be driven.",
 "wall": "Invisible Cloudflare Turnstile on sign-up form",
 "plan_scope": "",
 "robots_stop": null,
 "robots": null,
 "plain": {
  "summary": "Todoist is a task manager with a well-documented API and an official connector for AI agents. An agent could read all the documentation and even register as a developer client on its own, but it could not actually create a Todoist account because the sign-up page has an invisible robot check that blocked it. To finish that step for it, so the agent never got any further.",
  "can_do": [
   "Read the full product documentation and technical reference without an account",
   "Look up how the login and connection system works without an account",
   "Register itself as a technical client type, though this still needs a working account to use"
  ],
  "cannot_do": [
   {
    "what": "Create a Todoist account",
    "why": "An invisible robot check on the sign-up page rejected the automated attempt"
   },
   {
    "what": "Get a working login key or token",
    "why": "Every way to get one requires an account that could not be created"
   },
   {
    "what": "Add, schedule, organize or complete any task",
    "why": "No account or login key was ever obtained"
   }
  ]
 },
 "plan_gated": [],
 "reply": null,
 "capabilities": [
  {
   "id": "cap-01",
   "group": "Capture",
   "capability": "Capture a task from natural language (quick add)",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /api/v1/tasks",
    "mcp": null,
    "cli": null,
    "ui": "Quick Add (+) anywhere in app"
   },
   "check": "GET /api/v1/tasks/{id} returns the task with content/due parsed from the input string",
   "source": "https://www.todoist.com/; https://developer.todoist.com/api/v1/"
  },
  {
   "id": "cap-02",
   "group": "Capture",
   "capability": "Capture tasks by speaking (Ramble voice-to-task)",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Quick Add mic / Ramble"
   },
   "check": "New task(s) appear in Inbox matching the spoken content",
   "source": "https://www.todoist.com/ (Ramble feature); https://www.todoist.com/pricing (Ramble listed under Beginner, Unlimited Ramble under Pro)"
  },
  {
   "id": "cap-03",
   "group": "Scheduling",
   "capability": "Schedule a task with due date, time, and recurrence",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST/POST /api/v1/tasks (due_string/due_date/due_datetime/due_recurring)",
    "mcp": null,
    "cli": null,
    "ui": "Task due-date picker"
   },
   "check": "GET /api/v1/tasks/{id} shows due.date / due.is_recurring set as configured",
   "source": "https://developer.todoist.com/api/v1/ (Tasks: Add a task); https://www.todoist.com/pricing (Due dates & times)"
  },
  {
   "id": "cap-04",
   "group": "Scheduling",
   "capability": "Set a task deadline (separate from due date)",
   "weight": "core",
   "plan": "paid",
   "surfaces": {
    "api": "POST/POST /api/v1/tasks (deadline)",
    "mcp": null,
    "cli": null,
    "ui": "Task detail > Deadline"
   },
   "check": "GET /api/v1/tasks/{id} returns deadline.date",
   "source": "https://www.todoist.com/pricing (Deadlines, Pro feature)"
  },
  {
   "id": "cap-05",
   "group": "Organization",
   "capability": "Organize tasks into projects",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /api/v1/projects; POST /api/v1/tasks (project_id)",
    "mcp": null,
    "cli": null,
    "ui": "Sidebar > Add project"
   },
   "check": "GET /api/v1/projects/{id} exists and GET /api/v1/tasks?project_id={id} lists the task",
   "source": "https://developer.todoist.com/api/v1/ (Projects: Add a project); https://www.todoist.com/pricing (Personal projects)"
  },
  {
   "id": "cap-06",
   "group": "Organization",
   "capability": "Break a task into sub-tasks",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /api/v1/tasks (parent_id)",
    "mcp": null,
    "cli": null,
    "ui": "Task detail > Add sub-task / indent"
   },
   "check": "GET /api/v1/tasks/{id} shows parent_id referencing the parent task",
   "source": "https://www.todoist.com/pricing (Sub-tasks)"
  },
  {
   "id": "cap-07",
   "group": "Organization",
   "capability": "Prioritize tasks with priority levels",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST/POST /api/v1/tasks (priority)",
    "mcp": null,
    "cli": null,
    "ui": "Task flag/priority picker (p1-p4)"
   },
   "check": "GET /api/v1/tasks/{id} returns the set priority value",
   "source": "https://www.todoist.com/pricing (Priority levels)"
  },
  {
   "id": "cap-08",
   "group": "Completion",
   "capability": "Mark a task done / reopen it",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /api/v1/tasks/{id}/close; POST /api/v1/tasks/{id}/reopen",
    "mcp": null,
    "cli": null,
    "ui": "Task checkbox"
   },
   "check": "GET /api/v1/tasks/{id} shows is_completed true after close, false after reopen",
   "source": "https://developer.todoist.com/api/v1/ (Tasks: Close task, Complete task, Uncomplete item)"
  },
  {
   "id": "cap-09",
   "group": "Views",
   "capability": "View tasks in List, Board, or Calendar layout",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Project view-switcher"
   },
   "check": "Project header shows selected layout persisted on reload (calendar requires Pro)",
   "source": "https://www.todoist.com/pricing (Task views: List/Board/Calendar layout)"
  },
  {
   "id": "cap-10",
   "group": "Views",
   "capability": "Build and save a custom filter view",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /api/v1/filters",
    "mcp": null,
    "cli": null,
    "ui": "Sidebar > Filters & Labels > Add filter"
   },
   "check": "GET /api/v1/filters/{id} returns the saved query; filtered task list matches the query",
   "source": "https://developer.todoist.com/api/v1/ (Filters: Add a filter); https://www.todoist.com/pricing (Custom filters: 3 free, 150 Pro)"
  },
  {
   "id": "cap-11",
   "group": "Secondary",
   "capability": "Tag tasks with labels",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /api/v1/labels; POST /api/v1/tasks (labels)",
    "mcp": null,
    "cli": null,
    "ui": "Task detail > Labels (@label)"
   },
   "check": "GET /api/v1/tasks/{id} returns labels array containing the applied label name",
   "source": "https://developer.todoist.com/api/v1/ (Labels: Add a personal label)"
  },
  {
   "id": "cap-12",
   "group": "Secondary",
   "capability": "Group tasks into sections within a project",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /api/v1/sections",
    "mcp": null,
    "cli": null,
    "ui": "Project > Add section"
   },
   "check": "GET /api/v1/sections/{id} exists and tasks list that section_id",
   "source": "https://developer.todoist.com/api/v1/ (Sections: Add a section)"
  },
  {
   "id": "cap-13",
   "group": "Secondary",
   "capability": "Comment on a task or project (with file attachments)",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /api/v1/comments",
    "mcp": null,
    "cli": null,
    "ui": "Task detail > Comments"
   },
   "check": "GET /api/v1/comments?task_id={id} returns the posted comment/attachment",
   "source": "https://developer.todoist.com/api/v1/ (Comments: Task comments, Project Comments, File Attachments)"
  },
  {
   "id": "cap-14",
   "group": "Secondary",
   "capability": "Set a reminder on a task",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "POST /api/v1/reminders",
    "mcp": null,
    "cli": null,
    "ui": "Task detail > Remind me"
   },
   "check": "GET /api/v1/reminders?item_id={id} returns the reminder entry",
   "source": "https://developer.todoist.com/api/v1/ (Reminders: Add a reminder); https://www.todoist.com/pricing (Custom task reminders, Pro)"
  },
  {
   "id": "cap-15",
   "group": "Secondary",
   "capability": "Share a project and assign tasks to collaborators",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /api/v1/projects/{id}/collaborators; POST /api/v1/tasks (responsible_uid)",
    "mcp": null,
    "cli": null,
    "ui": "Project > Share / Task > Assign"
   },
   "check": "GET /api/v1/tasks/{id} shows responsible_uid set to the assigned collaborator",
   "source": "https://developer.todoist.com/api/v1/ (Sharing: Collaborators, Share a project); https://www.todoist.com/pricing (Assigned tasks)"
  },
  {
   "id": "cap-16",
   "group": "Secondary",
   "capability": "Start a project from a template (own or shared library)",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Templates gallery / Import template"
   },
   "check": "New project appears pre-populated with the template's tasks/sections",
   "source": "https://www.todoist.com/templates; https://www.todoist.com/pricing (Project templates)"
  },
  {
   "id": "cap-17",
   "group": "Secondary",
   "capability": "Reorder/move tasks, sections, and projects (drag-and-drop or API)",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /api/v1/tasks/{id}/move; POST /api/v1/sections/{id}/reorder; POST /api/v1/projects/{id}/reorder",
    "mcp": null,
    "cli": null,
    "ui": "Drag and drop in sidebar/project"
   },
   "check": "GET on the moved object reflects new project_id/section_id/order",
   "source": "https://developer.todoist.com/api/v1/ (Tasks: Move a task, Reorder tasks; Projects: Move a project, Reorder projects)"
  },
  {
   "id": "cap-18",
   "group": "Secondary",
   "capability": "Review productivity stats and completed-task activity history",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "GET /api/v1/tasks/completed; GET productivity stats endpoint",
    "mcp": null,
    "cli": null,
    "ui": "Activity log / Karma view"
   },
   "check": "Activity log lists completed task entries within the plan's history window (1 week free, full history Pro)",
   "source": "https://developer.todoist.com/api/v1/ (User: User productivity stats); https://www.todoist.com/pricing (1 week / Full reporting history)"
  },
  {
   "id": "cap-19",
   "group": "Secondary",
   "capability": "Connect calendar and email to create/sync tasks",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings > Integrations > Calendar / Email forwarding"
   },
   "check": "Calendar events or forwarded emails appear as tasks/synced entries in Todoist",
   "source": "https://www.todoist.com/pricing (Integrate email, calendar, and more); https://www.todoist.com/integrations"
  },
  {
   "id": "cap-20",
   "group": "Secondary",
   "capability": "Get AI-assisted task suggestions and breakdowns (Task Assist)",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Task detail > Task Assist (AI icon)"
   },
   "check": "Task Assist panel returns AI-generated sub-task or description suggestions for the task",
   "source": "https://www.todoist.com/pricing (Task Assist, Pro feature)"
  },
  {
   "id": "cap-21",
   "group": "Teamwork",
   "capability": "Create a shared team workspace",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "POST /api/v1/workspaces",
    "mcp": null,
    "cli": null,
    "ui": "Sidebar > Add team / workspace"
   },
   "check": "GET /api/v1/workspaces/{id} returns the new workspace with the creator as admin",
   "source": "https://developer.todoist.com/api/v1/ (Workspace: Add a workspace); https://www.todoist.com/pricing (A team workspace, Business)"
  },
  {
   "id": "cap-22",
   "group": "Teamwork",
   "capability": "Create team projects and organize them into folders",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "POST /api/v1/projects (workspace_id); POST /api/v1/folders",
    "mcp": null,
    "cli": null,
    "ui": "Workspace > Add project / folder"
   },
   "check": "GET /api/v1/projects/{id} shows workspace_id set; GET /api/v1/folders/{id} lists grouped projects",
   "source": "https://developer.todoist.com/api/v1/ (Folders: Add a folder); https://www.todoist.com/pricing (Team projects, Team project folders)"
  },
  {
   "id": "cap-23",
   "group": "Teamwork",
   "capability": "Invite workspace users and set their team role/permissions",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "POST /api/v1/workspaces/{id}/invite; POST workspace user role endpoint",
    "mcp": null,
    "cli": null,
    "ui": "Workspace settings > Members"
   },
   "check": "GET /api/v1/workspaces/{id}/users lists the invited user with the assigned role",
   "source": "https://developer.todoist.com/api/v1/ (Workspace users: Invite Users to a Workspace, Change user role)"
  },
  {
   "id": "cap-24",
   "group": "Teamwork",
   "capability": "View team activity log across a workspace",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Workspace > Activity"
   },
   "check": "Workspace activity log lists granular per-member actions (create/complete/move)",
   "source": "https://www.todoist.com/pricing (Granular team activity logs, Business)"
  },
  {
   "id": "cap-25",
   "group": "Peripheral",
   "capability": "Automate Todoist via personal API token or OAuth app",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": "OAuth authorize/token endpoints",
    "mcp": null,
    "cli": null,
    "ui": "Settings > Integrations > Developer"
   },
   "check": "Token/OAuth flow returns an access token that authenticates subsequent REST calls",
   "source": "https://developer.todoist.com/api/v1/ (Authorization: OAuth, Dynamic Client Registration)"
  },
  {
   "id": "cap-26",
   "group": "Peripheral",
   "capability": "Drive Todoist through its CLI",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "todoist (task/project commands)",
    "ui": null
   },
   "check": "CLI command output reflects the same task state visible in the app/API",
   "source": "https://developer.todoist.com/api/v1/ (sidebar: Todoist CLI - Installation, Common commands)"
  },
  {
   "id": "cap-28",
   "group": "Peripheral",
   "capability": "Set up SSO/SCIM and security controls for an organization",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Workspace admin > Security"
   },
   "check": "Workspace admin panel shows SSO configured and enforced for sign-in",
   "source": "https://trustcenter.doist.com/; https://www.todoist.com/pricing (SOC2 Type II)"
  },
  {
   "id": "cap-29",
   "group": "Peripheral",
   "capability": "Manage centralized team billing for a workspace",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Workspace settings > Billing"
   },
   "check": "Billing page shows a single invoice/subscription covering all workspace members",
   "source": "https://www.todoist.com/pricing (Centralized team billing, Business)"
  },
  {
   "id": "cap-30",
   "group": "Peripheral",
   "capability": "Upload a file attachment to a task (size limited by plan)",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": "POST /api/v1/uploads; POST /api/v1/comments (file_attachment)",
    "mcp": null,
    "cli": null,
    "ui": "Task comment > Attach file"
   },
   "check": "GET /api/v1/comments returns the comment with a file_attachment object referencing the uploaded file",
   "source": "https://developer.todoist.com/api/v1/ (Comments: File Attachments); https://www.todoist.com/pricing (File uploads: 5MB free / 100MB Pro)"
  }
 ],
 "attempts": [
  {
   "t": "01:43",
   "cap": "discovery",
   "route": "api",
   "documented": true,
   "verified": true,
   "capability": "robots.txt / aipref",
   "task": "Read robots.txt on todoist.com, app.todoist.com, developer.todoist.com, api.todoist.com",
   "result": "done",
   "evidence": "todoist.com robots: User-Agent * Allow /; Disallow /app/, /api/, /auth/ ... no Content-Usage or Content-signal lines. app.todoist.com: Disallow / with Allow /auth/login, /auth/signup, /auth/password. developer.todoist.com: Disallow / Allow /$ Allow /api/v1/. api.todoist.com/robots.txt 404 (no rules).",
   "notes": "No Content-Usage header seen on todoist.com or developer.todoist.com responses."
  },
  {
   "t": "01:43",
   "cap": "discovery",
   "route": "api",
   "documented": true,
   "verified": true,
   "capability": "docs + OpenAPI",
   "task": "Fetch API reference and its spec",
   "result": "done",
   "evidence": "https://developer.todoist.com/api/v1/ (Redoc) embeds OpenAPI 'openapi':'3.1.0', info.version 1, server https://api.todoist.com/, 78 paths / 108 operations, plus Sync endpoint, Webhooks, MCP and CLI sections. Saved openapi.json.",
   "notes": "No standalone spec URL found; spec extracted from the page's __redoc_state."
  },
  {
   "t": "01:50",
   "cap": "discovery",
   "route": "api",
   "documented": true,
   "verified": true,
   "capability": "llms.txt / markdown",
   "task": "llms.txt and markdown docs",
   "result": "failed",
   "evidence": "todoist.com/llms.txt 301 -> 404 HTML; developer.todoist.com/llms.txt 404. Accept: text/markdown on developer docs and todoist.com returned text/html, no Vary: Accept. developer.todoist.com/api/v1.md 404."
  },
  {
   "t": "01:50",
   "cap": "discovery",
   "route": "api",
   "documented": true,
   "verified": true,
   "capability": "agent cards",
   "task": "AI catalog, A2A card, server card",
   "result": "failed",
   "evidence": "todoist.com/.well-known/ai-catalog.json, agent-card.json, agent.json, ucp: 404 HTML. ai.todoist.net/mcp/server-card 404 JSON; ai.todoist.net/.well-known/ai-catalog.json 404."
  },
  {
   "t": "01:50",
   "cap": "discovery",
   "route": "api",
   "documented": true,
   "verified": true,
   "capability": "MCP server/discover",
   "task": "POST server/discover to https://ai.todoist.net/mcp unauthenticated",
   "result": "partial",
   "evidence": "401 {\"message\":\"Missing or invalid authorization header\"}, WWW-Authenticate: Bearer resource_metadata=\"https://ai.todoist.net/.well-known/oauth-protected-resource/mcp\"; PRM 200 JSON resource https://ai.todoist.net/mcp, authorization_servers [https://todoist.com], scopes data:read_write.",
   "notes": "Auth required before any protocol answer; retry with token later."
  },
  {
   "t": "01:50",
   "cap": "discovery",
   "route": "api",
   "documented": true,
   "verified": true,
   "capability": "OAuth AS metadata",
   "task": "Read RFC 8414 metadata and API PRM",
   "result": "done",
   "evidence": "todoist.com/.well-known/oauth-authorization-server: client_id_metadata_document_supported true, registration_endpoint https://todoist.com/oauth/register, grant_types authorization_code+refresh_token, S256 only, resource_parameter_supported true; no device_authorization_endpoint, no agent_auth block. api.todoist.com/.well-known/oauth-protected-resource 200 JSON."
  },
  {
   "t": "04:01",
   "cap": "signup",
   "capability": "Sign up",
   "task": "Create a free account with email+password at app.todoist.com/auth/signup",
   "route": "browser",
   "documented": true,
   "result": "blocked",
   "verified": true,
   "evidence": "No documented API sign-up (OpenAPI has none). Browser form: filled email the agent's inbox + password, clicked 'Sign up with Email' -> page error 'Captcha verification failed. Please try again.' No visible widget (pw: visible_challenge false). Auth bundle vendors~authentication~app.*.js loads Cloudflare Turnstile ('cf-turnstile-script', window.turnstile.getResponse).",
   "notes": "Invisible Cloudflare Turnstile on the sign-up form rejected our agent's browser. Not retried. Only other routes: Google/Facebook/Apple, which we have no account for.",
   "quality": {
    "error_legibility": "clear",
    "recoverable": "no"
   }
  },
  {
   "t": "05:20",
   "cap": "credentials",
   "capability": "Get API credentials",
   "task": "Register an OAuth client (DCR) and start authorization code + PKCE flow",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": true,
   "evidence": "POST https://todoist.com/oauth/register -> 201 client_id tdd_1939…, token_endpoint_auth_method none (DCR works headless). Authorize with resource=https://api.todoist.com -> redirect error=invalid_target; with resource=https://ai.todoist.net/mcp -> app.todoist.com/auth/login. Personal token lives at app.todoist.com/app/settings/integrations (docs). All paths need a logged-in account, which we could not create (Turnstile on sign-up).",
   "notes": "AS metadata lists no device_authorization_endpoint and no agent_auth block. resource=https://api.todoist.com (the API's own PRM 'resource') is refused as invalid_target.",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "05:20",
   "cap": "first_call",
   "capability": "First API call",
   "task": "GET /api/v1/tasks",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": true,
   "evidence": "401 {\"error\":\"Unauthorized\",\"error_code\":477,\"error_tag\":\"UNAUTHORIZED\",\"http_code\":401}, retry-after 5; with a dummy bearer 401 + WWW-Authenticate: Bearer error=\"invalid_token\", resource_metadata=\"https://api.todoist.com/.well-known/oauth-protected-resource\". No token obtainable without an account.",
   "notes": "Errors are JSON (application/json, not problem+json) with error_tag/error_code; Retry-After rose on each unauthenticated call (5, 11, 33, 129 s).",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "05:20",
   "cap": "pay",
   "capability": "Pay step probes",
   "task": "402 / x402 / MPP / UCP / registries / billing API",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Unauthenticated calls: no 402 anywhere (401/403/400 JSON). x402./mpp./agents.todoist.com do not resolve. /.well-known/ucp 404. No x-payment-info in OpenAPI. x402 Bazaar and mpp.dev/api/services: 0 mentions of todoist. OpenAPI Billing: POST /api/v1/payments/cancel_plan_with_redirect_to_stripe ('Start a hosted cancellation flow and return the redirect URL'), /payments/reactivate_plan, /payments/get_subscription_info, /usage_billing/top_up ('create a hosted Stripe Checkout session to top up ... Automations wallet', requires active personal Pro). Pricing page: Beginner (free), Pro, Business ('Start for free').",
   "notes": "Upgrade checkout itself not reached (no account)."
  },
  {
   "t": "05:20",
   "cap": "cap-01",
   "capability": "Capture a task from natural language (quick add)",
   "task": "Try: Capture a task from natural language (quick add) via POST /api/v1/tasks",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-02",
   "capability": "Capture tasks by speaking (Ramble voice-to-task)",
   "task": "Try: Capture tasks by speaking (Ramble voice-to-task) via UI",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-03",
   "capability": "Schedule a task with due date, time, and recurrence",
   "task": "Try: Schedule a task with due date, time, and recurrence via POST/POST /api/v1/tasks (due_string/due_date/due_datetime/due_recurring)",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-04",
   "capability": "Set a task deadline (separate from due date)",
   "task": "Try: Set a task deadline (separate from due date) via POST/POST /api/v1/tasks (deadline)",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile; also needs a paid plan per the capability map."
  },
  {
   "t": "05:20",
   "cap": "cap-05",
   "capability": "Organize tasks into projects",
   "task": "Try: Organize tasks into projects via POST /api/v1/projects; POST /api/v1/tasks (project_id)",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-06",
   "capability": "Break a task into sub-tasks",
   "task": "Try: Break a task into sub-tasks via POST /api/v1/tasks (parent_id)",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-07",
   "capability": "Prioritize tasks with priority levels",
   "task": "Try: Prioritize tasks with priority levels via POST/POST /api/v1/tasks (priority)",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-08",
   "capability": "Mark a task done / reopen it",
   "task": "Try: Mark a task done / reopen it via POST /api/v1/tasks/{id}/close; POST /api/v1/tasks/{id}/reopen",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-09",
   "capability": "View tasks in List, Board, or Calendar layout",
   "task": "Try: View tasks in List, Board, or Calendar layout via UI",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-10",
   "capability": "Build and save a custom filter view",
   "task": "Try: Build and save a custom filter view via POST /api/v1/filters",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-11",
   "capability": "Tag tasks with labels",
   "task": "Try: Tag tasks with labels via POST /api/v1/labels; POST /api/v1/tasks (labels)",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-12",
   "capability": "Group tasks into sections within a project",
   "task": "Try: Group tasks into sections within a project via POST /api/v1/sections",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-13",
   "capability": "Comment on a task or project (with file attachments)",
   "task": "Try: Comment on a task or project (with file attachments) via POST /api/v1/comments",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-14",
   "capability": "Set a reminder on a task",
   "task": "Try: Set a reminder on a task via POST /api/v1/reminders",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile; also needs a paid plan per the capability map."
  },
  {
   "t": "05:20",
   "cap": "cap-15",
   "capability": "Share a project and assign tasks to collaborators",
   "task": "Try: Share a project and assign tasks to collaborators via POST /api/v1/projects/{id}/collaborators; POST /api/v1/tasks (responsible_uid)",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-16",
   "capability": "Start a project from a template (own or shared library)",
   "task": "Try: Start a project from a template (own or shared library) via UI",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-17",
   "capability": "Reorder/move tasks, sections, and projects (drag-and-drop or API)",
   "task": "Try: Reorder/move tasks, sections, and projects (drag-and-drop or API) via POST /api/v1/tasks/{id}/move; POST /api/v1/sections/{id}/reorder; POST /api/v1/projects/{id}/reorder",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-18",
   "capability": "Review productivity stats and completed-task activity history",
   "task": "Try: Review productivity stats and completed-task activity history via GET /api/v1/tasks/completed; GET productivity stats endpoint",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-19",
   "capability": "Connect calendar and email to create/sync tasks",
   "task": "Try: Connect calendar and email to create/sync tasks via UI",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-20",
   "capability": "Get AI-assisted task suggestions and breakdowns (Task Assist)",
   "task": "Try: Get AI-assisted task suggestions and breakdowns (Task Assist) via UI",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile; also needs a paid plan per the capability map."
  },
  {
   "t": "05:20",
   "cap": "cap-21",
   "capability": "Create a shared team workspace",
   "task": "Try: Create a shared team workspace via POST /api/v1/workspaces",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile; also needs a paid plan per the capability map."
  },
  {
   "t": "05:20",
   "cap": "cap-22",
   "capability": "Create team projects and organize them into folders",
   "task": "Try: Create team projects and organize them into folders via POST /api/v1/projects (workspace_id); POST /api/v1/folders",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile; also needs a paid plan per the capability map."
  },
  {
   "t": "05:20",
   "cap": "cap-23",
   "capability": "Invite workspace users and set their team role/permissions",
   "task": "Try: Invite workspace users and set their team role/permissions via POST /api/v1/workspaces/{id}/invite; POST workspace user role endpoint",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile; also needs a paid plan per the capability map."
  },
  {
   "t": "05:20",
   "cap": "cap-24",
   "capability": "View team activity log across a workspace",
   "task": "Try: View team activity log across a workspace via UI",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile; also needs a paid plan per the capability map."
  },
  {
   "t": "05:20",
   "cap": "cap-25",
   "capability": "Automate Todoist via personal API token or OAuth app",
   "task": "Try: Automate Todoist via personal API token or OAuth app via OAuth authorize/token endpoints",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-26",
   "capability": "Drive Todoist through its CLI",
   "task": "Try: Drive Todoist through its CLI via UI",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  },
  {
   "t": "05:20",
   "cap": "cap-28",
   "capability": "Set up SSO/SCIM and security controls for an organization",
   "task": "Try: Set up SSO/SCIM and security controls for an organization via UI",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile; also needs a paid plan per the capability map."
  },
  {
   "t": "05:20",
   "cap": "cap-29",
   "capability": "Manage centralized team billing for a workspace",
   "task": "Try: Manage centralized team billing for a workspace via UI",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile; also needs a paid plan per the capability map."
  },
  {
   "t": "05:20",
   "cap": "cap-30",
   "capability": "Upload a file attachment to a task (size limited by plan)",
   "task": "Try: Upload a file attachment to a task (size limited by plan) via POST /api/v1/uploads; POST /api/v1/comments (file_attachment)",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account: sign-up blocked by invisible Cloudflare Turnstile, so no API token, OAuth grant or MCP session could be obtained."
  }
 ],
 "stale": false,
 "icon": "/logos/todoist.png",
 "monitored": false,
 "verdict": "Gets in on its own nowhere yet: L1 · Needs a person. Our agent stopped at signup, where the email form at app.todoist.com runs an invisible Cloudflare Turnstile that rejected our agent's browser, with no visible challenge shown and no Google, Facebook or Apple account on hand. Dynamic client registration worked headless, but every token path still needed a logged-in account, so no key, call or work followed. Paying and cancelling both end in a hosted Stripe page per the docs, untested, and deletion has no documented route. The API, CLI and official MCP server stand ready once a person signs up and hands over a key.",
 "page": "https://agentdrives.com/tools/todoist?via=api"
}