{
 "slug": "basecamp",
 "name": "Basecamp",
 "url": "https://basecamp.com",
 "domain": "basecamp.com",
 "category": "project-management",
 "category_name": "Project management",
 "tested_at": "2026-10-02",
 "run": "20261002T134720Z",
 "draft": false,
 "reviewed": true,
 "owner_verified": null,
 "origin": "editorial",
 "history": [
  {
   "run": "20261001T220735Z",
   "date": "2026-10-01",
   "level": 4,
   "engine": {
    "runner": "omp",
    "model": null,
    "driver": null,
    "signed": true,
    "inbox": [
     "agentdrives.com"
    ],
    "robots": "start"
   }
  },
  {
   "run": "20261002T134720Z",
   "date": "2026-10-02",
   "level": 4,
   "engine": {
    "runner": "omp",
    "model": "claude-opus-5-5",
    "driver": 2,
    "signed": true,
    "inbox": [
     "agentdrives.com"
    ],
    "robots": "start"
   }
  }
 ],
 "level": 4,
 "level_name": "Runs on its own",
 "level_selfhost": null,
 "entry": "self-start",
 "door": {
  "passed": 2,
  "tries": 2,
  "self_start": true
 },
 "badges": [
  "agent-can-leave"
 ],
 "stages": [
  {
   "key": "in",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: sign-up in a browser"
  },
  {
   "key": "work",
   "label": "Use",
   "state": "yes",
   "text": "Work done: 100% of the core"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "part",
   "text": "Reaches the checkout: stopped at the card form",
   "value": "ready",
   "route": "card_checkout"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Leaves on its own: cancels on its own, deletes its account",
   "left": "deleted"
  }
 ],
 "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": "yes",
   "text": "Gets in on its own: sign-up in a browser",
   "stage": "in"
  },
  {
   "key": "use",
   "label": "Use",
   "state": "yes",
   "text": "Work done: 100% of the core",
   "stage": "work"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "part",
   "text": "Reaches the checkout: stopped at the card form",
   "value": "ready",
   "route": "card_checkout",
   "stage": "pay"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Leaves on its own: cancels on its own, deletes its account",
   "left": "deleted",
   "stage": "leave"
  }
 ],
 "access": [
  {
   "key": "browser_signup",
   "label": "Sign-up in a browser",
   "routes": [],
   "minutes": 3.1,
   "core": "9/9"
  }
 ],
 "minutes": 3.1,
 "next": {
  "to": 5,
  "text": "Next: pay without a person"
 },
 "stop": null,
 "core": "9/9",
 "scores": {
  "coverage": 91,
  "reliability": 78,
  "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": []
 },
 "reliability_method": "first-try",
 "resilience": null,
 "stress": [],
 "surface_audit": null,
 "coverage_core": 100,
 "after_wall": null,
 "coverage_source": "computed",
 "driver": {
  "version": 2,
  "model": "claude-opus-5-5",
  "profile": "full",
  "assisted": false,
  "handoff": null,
  "prompt_sha": null,
  "kb_version": null,
  "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": 2,
 "drives": 2,
 "works_assisted": null,
 "freshness": "fresh",
 "nothing_to_pay": false,
 "core_gated": false,
 "profiles": {},
 "agent_check": null,
 "agent_pass": {
  "rung": "signup",
  "vendor": "hCaptcha (script loaded, invisible)",
  "signed": true
 },
 "who_gets_in": {
  "server": {
   "state": "in"
  },
  "signed": {
   "state": "page",
   "kind": "signup",
   "at": "2026-10-13"
  },
  "browser": {
   "state": "in",
   "measured": false
  },
  "our_key": "pending",
  "robots": null,
  "tip": false
 },
 "ladder": {
  "docs": {
   "status": "headless",
   "note": "basecamp.com/agents links the official CLI (with agent skill and built-in MCP server), the SDKs (openapi.json 3.1, 278 operations) and the bc3-api reference; OAuth metadata at /.well-known. No llms.txt."
  },
  "signup": {
   "status": "headless",
   "note": "The public free-plan sign-up form (app.basecamp.com/signup/account) accepted a plain HTTP form POST from our signed agent and redirected straight into the new account. hCaptcha is loaded on the page but no challenge was served."
  },
  "verify": {
   "status": "browser",
   "note": "Sign-up needs no email verification. The first password login asks for a 6-character code sent by email; we read it headless from our inbox and typed it into the login page in the browser."
  },
  "credentials": {
   "status": "browser",
   "note": "Documented route: `basecamp auth login --device-code` (OAuth device flow). Approving the code needs a logged-in browser session and a confirmation checkbox. Each approval gave a token for only the one account picked on the page.",
   "via": ""
  },
  "first_call": {
   "status": "headless",
   "note": "basecamp projects list --json and GET https://3.basecampapi.com/[redacted]/projects.json both 200."
  },
  "first_action": {
   "status": "headless",
   "note": "POST /projects.json created a project (after trashing the auto-made one: Free allows 1 project; the limit returns 507)."
  },
  "pay": {
   "status": "browser",
   "grade": "P2",
   "rails": [],
   "first_party": false,
   "rail_scope": "none",
   "trial_path": "no-card trial",
   "note": "No 402, x402, MPP, L402, UCP or billing API, CLI or MCP tool. x402./mpp./agents. subdomains have no DNS. Basecamp is not listed in the x402 Bazaar, mpp.dev or projects.dev. You upgrade on an in-app page (Adminland -> plans -> card number, expiry, CVV and billing address -> 'Buy Basecamp'). An agent holding a card could fill it in. This was not submitted (no card), so 3DS behaviour is unknown. 30-day trials of paid plans need no card."
  },
  "cancel": {
   "status": "browser",
   "grade": "X3",
   "note": "Adminland -> 'Cancel this account' -> one confirm button; no retention flow. There is no API or CLI route. Done for the no-card Pro trial account, and the API then returned 404."
  },
  "delete": {
   "status": "browser",
   "note": "Records were deleted via the API (all 204). Both accounts were cancelled in the web UI (data deleted within 30 days, per the page). The Basecamp ID (login) remains, and Launchpad shows no self-serve option to delete it.",
   "left": "deleted",
   "account": true
  }
 },
 "routes": [],
 "checkout": null,
 "docs": null,
 "claims": null,
 "pay_options": {
  "checked": "2026-10-02",
  "source": "drive",
  "options": [],
  "agentic": [],
  "paid": null,
  "exercised": null,
  "detected_grade": null,
  "trial": {
   "no_card": true,
   "card_required": null,
   "free_plan": null
  },
  "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 JSON at 3.basecampapi.com/{account}, 71 documented sections",
  "openapi": "basecamp-sdk/openapi.json, OpenAPI 3.1, 186 paths / 278 operations, no servers block",
  "cli": "official Go CLI v0.11.0: JSON envelope with ok, code, retryable and breadcrumbs, `--help --agent`",
  "sdk": "Go, Ruby, TypeScript (@37signals/basecamp 0.21.0, tested), Swift, Kotlin",
  "mcp": "official, built into the CLI (`basecamp mcp`, stdio): 15 domain tools (README says 16)",
  "webhooks": "per project; delivery log with request and response visible via GET /webhooks/{id}.json"
 },
 "can_do": [
  "Sign up for the free plan with a plain HTTP form post",
  "Create a project and turn on its tools (Card Table, Check-ins, Email Forwards)",
  "Create to-do lists and to-dos with assignees, due dates and subtasks; complete and reopen them",
  "Post messages and comments, chat in Campfire, boost posts",
  "Create cards and move them across Card Table columns",
  "Add calendar events and read them back, also via the project's iCal feed",
  "Track to-do lists on a Hill Chart (moving the dot needs the web UI)",
  "Upload files, make folders and documents",
  "Set up automatic check-in questions",
  "Read reports, Everything views, My Assignments, search, backlinks",
  "Register webhooks and inspect their delivery log",
  "Add teammates, rename the account, set out-of-office",
  "On a no-card Pro trial: create templates, build projects from them, log time, upload a logo",
  "Drive all of it through the official CLI or its built-in MCP server"
 ],
 "cannot_do": [
  {
   "what": "Get an API token without a browser",
   "why": "The device-flow code must be approved on a logged-in web page; there is no self-serve agent client registration (the client_credentials 'agent' principal is created inside Basecamp)"
  },
  {
   "what": "Move a Hill Chart dot via API",
   "why": "Only track/untrack and read are documented; the web UI slider works"
  },
  {
   "what": "Send a Ping (1:1 chat)",
   "why": "No ping endpoint in bc3-api, the CLI or MCP"
  },
  {
   "what": "Receive an email forward headless",
   "why": "The inbox API does not expose the forwarding address; forwards can only be read"
  },
  {
   "what": "Upgrade, cancel or delete the account via API",
   "why": "No billing or account-lifecycle endpoints; the web UI only"
  },
  {
   "what": "Delete the Basecamp ID (login)",
   "why": "No self-serve option seen on Launchpad"
  }
 ],
 "blockers": [
  "OAuth device approval requires a logged-in browser session (one human-or-browser step before any API use)"
 ],
 "tips_for_owner": [
  "Let agents get a token without a browser",
  "Make the device-approval account scope match its wording",
  "Add a billing and cancellation API",
  "Expose pings and Hill Chart positions in the API",
  "Return a plan reason on plan-gated 403s",
  "Publish llms.txt and fix the MCP tool count in the README"
 ],
 "tips_for_agents": [
  "Use the official CLI (`basecamp ... --json`) or `basecamp mcp`. Errors come back with a stable `code` and `retryable`, and an unknown MCP action lists the valid ones.",
  "Run `basecamp auth login --device-code` and approve the code once in a logged-in browser. Pick the right account on that page: the token only works for that one.",
  "`basecamp mcp` exits unless BASECAMP_ACCOUNT_ID (or config) is set.",
  "The Free plan allows 1 project and sign-up already creates one: trash it (DELETE /projects/{id}.json) or POST /projects.json returns 507.",
  "Request bodies are often nested: {\"question\":{...}}, {\"boost\":{...}}, {\"project\":{...}}. A flat body gives a bare 422 with no field detail.",
  "PUT replaces omitted fields: updating a document without `title` resets it to 'Untitled'.",
  "Paths are flat (/todos/{id}.json) with /buckets/{project}/ aliases. Forwards are at /inboxes/{id}/inbox_forwards.json.",
  "Paid features (templates, time tracking, logo) are available on a no-card 30-day trial."
 ],
 "selfhost": null,
 "summary": "Basecamp is one of the most agent-ready products we've driven: a plain form POST signs up a free account, and the official CLI with its built-in MCP server, the REST API and the SDKs covered all nine core capabilities. The one browser step is approving the OAuth device code, and each token reaches only the account chosen there. Paying, cancelling and deleting are web-only, and paid trials need no card.",
 "wall": "Browser approval needed for first API key",
 "plan_scope": "free plan (core); no-card 30-day Pro trial for templates, time tracking and logo",
 "robots_stop": null,
 "robots": null,
 "plain": {
  "summary": "Basecamp is project-management software for teams: to-do lists, messages, chat, schedules and files in one place. An agent could sign up for a free account on its own and then run almost everything through Basecamp's official command-line tool, a connected AI-assistant interface, and its API, covering all the everyday project work. The one browser step was approving a one-time login code, which the agent did itself, before it could get an API key; paying for a paid plan and cancelling the account also require the web page.",
  "can_do": [
   "Sign itself up for a free account without a human",
   "Create and manage projects, to-do lists, messages, chats, schedules and files entirely through code",
   "Connect through the official AI-agent tool to do all of this with simple commands",
   "Try paid features for free for 30 days without a credit card",
   "Delete everything it created when done"
  ],
  "cannot_do": [
   {
    "what": "Get its first API key without a browser",
    "why": "A one-time login code must be approved on a logged-in web page (the agent did this in its browser)"
   },
   {
    "what": "Send a direct one-to-one chat message",
    "why": "That feature has no programmatic way to trigger it"
   },
   {
    "what": "Buy a paid plan or cancel without a browser",
    "why": "Payment and cancellation only exist as web pages, no API (the agent cancelled in its browser)"
   },
   {
    "what": "Delete its own login identity",
    "why": "No self-service option exists for that"
   }
  ]
 },
 "plan_gated": [
  {
   "capability": "Templates",
   "plan": "Freelancer/Studio/Pro (no-card trial worked)",
   "evidence": "Free: POST /templates.json -> 507 \"This account's package doesn't include templates.\""
  },
  {
   "capability": "Time tracking",
   "plan": "paid (no-card trial worked)",
   "evidence": "Free: POST /recordings/{id}/timesheet/entries.json -> 403 empty body; account.subscription.timesheet=false"
  },
  {
   "capability": "Branding (logo)",
   "plan": "paid (no-card trial worked)",
   "evidence": "Free: PUT /account/logo.json -> 403 empty body; account.subscription.logo=false"
  }
 ],
 "reply": null,
 "capabilities": [
  {
   "id": "cap-01",
   "group": "Projects",
   "capability": "Create a project",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /projects.json",
    "mcp": null,
    "cli": "basecamp project create",
    "ui": "Home → New project"
   },
   "check": "GET /projects/{id}.json returns the new project",
   "source": "https://github.com/basecamp/bc-api (sections/projects.md); https://basecamp.com/features"
  },
  {
   "id": "cap-02",
   "group": "Projects",
   "capability": "Add tools (message board, to-dos, chat, calendar, card table) to a project",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /projects/{id}/tools.json (sections/tools.md)",
    "mcp": null,
    "cli": "basecamp project tools",
    "ui": "Project page → Add tool"
   },
   "check": "GET /projects/{id}.json dock array shows tool with enabled:true",
   "source": "https://basecamp.com/features"
  },
  {
   "id": "cap-03",
   "group": "To-dos",
   "capability": "Create a to-do list and add to-dos with due dates, assignees, subtasks",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /todolists/{id}/todos.json",
    "mcp": null,
    "cli": "basecamp todo create",
    "ui": "Project → To-dos"
   },
   "check": "GET /todos/{id}.json shows assignee, due_on, and parent todolist",
   "source": "https://basecamp.com/features; https://github.com/basecamp/bc-api (sections/todos.md, sections/subtasks.md)"
  },
  {
   "id": "cap-04",
   "group": "To-dos",
   "capability": "Complete / reopen a to-do",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /todos/{id}/completion.json, DELETE /todos/{id}/completion.json",
    "mcp": null,
    "cli": "basecamp todo complete",
    "ui": "To-do list → check item"
   },
   "check": "GET /todos/{id}.json shows completed:true/false",
   "source": "https://github.com/basecamp/bc-api (sections/todos.md)"
  },
  {
   "id": "cap-05",
   "group": "Message Board",
   "capability": "Post and reply to messages/announcements",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /message_boards/{id}/messages.json, POST /recordings/{id}/comments.json",
    "mcp": null,
    "cli": "basecamp message post",
    "ui": "Project → Message Board"
   },
   "check": "GET /messages/{id}.json returns new post; comments list shows reply",
   "source": "https://basecamp.com/features; https://github.com/basecamp/bc-api (sections/messages.md, sections/comments.md)"
  },
  {
   "id": "cap-06",
   "group": "Card Table",
   "capability": "Track work through kanban-style Card Table stages",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /card_tables/{id}/columns/{col_id}/cards.json",
    "mcp": null,
    "cli": "basecamp card create",
    "ui": "Project → Card Table"
   },
   "check": "GET /card_table_cards/{id}.json shows column/step placement",
   "source": "https://basecamp.com/features; https://github.com/basecamp/bc-api (sections/card_table_cards.md, sections/card_table_columns.md)"
  },
  {
   "id": "cap-07",
   "group": "Chat",
   "capability": "Chat in real time via Campfire",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /campfires/{id}/lines.json",
    "mcp": null,
    "cli": "basecamp campfire send",
    "ui": "Project → Campfire"
   },
   "check": "GET /campfires/{id}/lines.json includes the new line",
   "source": "https://basecamp.com/features (Campfire chats)"
  },
  {
   "id": "cap-08",
   "group": "Scheduling",
   "capability": "Schedule deadlines, milestones, and events on a project calendar",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /schedules/{id}/entries.json",
    "mcp": null,
    "cli": "basecamp schedule add",
    "ui": "Project → Schedule"
   },
   "check": "GET /schedule_entries/{id}.json returns starts_at/ends_at",
   "source": "https://basecamp.com/features (The Basecamp Calendar); https://github.com/basecamp/bc-api (sections/schedule_entries.md)"
  },
  {
   "id": "cap-09",
   "group": "Hill Charts",
   "capability": "Visualize to-do list progress on a Hill Chart",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "GET /buckets/{p}/hill_charts/{id}.json",
    "mcp": null,
    "cli": null,
    "ui": "Project → To-do list → Hill Chart"
   },
   "check": "GET hill_chart shows updated dot position after moving",
   "source": "https://basecamp.com/hill-charts; https://github.com/basecamp/bc-api (sections/hill_charts.md)"
  },
  {
   "id": "cap-10",
   "group": "Docs & Files",
   "capability": "Upload, store, and organize files, documents, and cloud links in folders",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /vaults/{id}/uploads.json, POST /vaults/{id}/documents.json, POST /vaults/{id}/vaults.json",
    "mcp": null,
    "cli": "basecamp upload",
    "ui": "Project → Docs & Files"
   },
   "check": "GET /vaults/{id}.json lists the new file/folder",
   "source": "https://basecamp.com/features (Docs & Files); https://github.com/basecamp/bc-api (sections/uploads.md, sections/documents.md, sections/folders.md, sections/cloud_files.md)"
  },
  {
   "id": "cap-11",
   "group": "Automatic Check-ins",
   "capability": "Set up recurring automatic check-in questions for the team",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /questionnaires/{id}/questions.json",
    "mcp": null,
    "cli": null,
    "ui": "Project → Automatic Check-ins"
   },
   "check": "GET /question_answers.json shows submitted answers on schedule",
   "source": "https://basecamp.com/features (Automatic Check-ins); https://github.com/basecamp/bc-api (sections/questionnaires.md, sections/questions.md, sections/question_answers.md)"
  },
  {
   "id": "cap-12",
   "group": "Reports",
   "capability": "View cross-project Reports and Everything Views",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "GET /reports/..., GET /recordings.json?type=",
    "mcp": null,
    "cli": null,
    "ui": "Top nav → Reports / Everything"
   },
   "check": "Report page or GET /recordings.json?type=Todo returns items spanning multiple projects",
   "source": "https://basecamp.com/features (Reports; Everything Views); https://github.com/basecamp/bc-api (sections/reports.md, sections/recordings.md, sections/everything.md)"
  },
  {
   "id": "cap-13",
   "group": "Lineup",
   "capability": "See all projects plotted on a timeline (The Lineup)",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "GET/POST lineup_markers (sections/lineup_markers.md)",
    "mcp": null,
    "cli": null,
    "ui": "Top nav → Lineup"
   },
   "check": "Lineup page shows project bars by start/end date; GET lineup_markers reflects added marker",
   "source": "https://basecamp.com/features (The Lineup)"
  },
  {
   "id": "cap-14",
   "group": "My Bar",
   "capability": "View personal assignments, bookmarks, and notes across projects",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "GET /my/assignments.json, GET /my/bookmarks.json, GET /my/notes.json",
    "mcp": null,
    "cli": null,
    "ui": "My Bar (bottom of screen)"
   },
   "check": "GET /my/assignments.json lists to-dos assigned to the current user",
   "source": "https://basecamp.com/features (My Tasks, Events, Today, Bookmarks, and Notes); https://github.com/basecamp/bc-api (sections/my_assignments.md, sections/my_bookmarks.md, sections/my_notes.md)"
  },
  {
   "id": "cap-15",
   "group": "Templates",
   "capability": "Create and apply reusable project/to-do list templates",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "POST /templates.json, POST /templates/{id}/project_constructions.json",
    "mcp": null,
    "cli": null,
    "ui": "Project templates"
   },
   "check": "GET /projects/{id}.json shows structure matching the template",
   "source": "https://basecamp.com/pricing (Project templates); https://github.com/basecamp/bc-api (sections/templates.md, sections/templatifications.md, sections/template_library.md)"
  },
  {
   "id": "cap-16",
   "group": "Time tracking",
   "capability": "Track time spent on project work",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "sections/timesheets.md",
    "mcp": null,
    "cli": null,
    "ui": "Project → Time tracking"
   },
   "check": "GET timesheets endpoint returns logged hours entry",
   "source": "https://basecamp.com/pricing (Time tracking)"
  },
  {
   "id": "cap-17",
   "group": "Search",
   "capability": "Search across all content in Basecamp",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "GET /search (sections/search.md)",
    "mcp": null,
    "cli": "basecamp search",
    "ui": "Top nav → Search"
   },
   "check": "Search results include the term from a created message/to-do",
   "source": "https://github.com/basecamp/bc-api (sections/search.md)"
  },
  {
   "id": "cap-18",
   "group": "Subscriptions & notifications",
   "capability": "Subscribe/unsubscribe to a recording and manage notification pings",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /recordings/{id}/subscription.json",
    "mcp": null,
    "cli": null,
    "ui": "Any post/to-do → Notify"
   },
   "check": "GET /recordings/{id}/subscription.json lists the subscriber",
   "source": "https://github.com/basecamp/bc-api (sections/subscriptions.md)"
  },
  {
   "id": "cap-19",
   "group": "Direct messages",
   "capability": "Send direct pings to teammates",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST pings (part of campfires/people sections)",
    "mcp": null,
    "cli": null,
    "ui": "People → Ping"
   },
   "check": "Ping thread shows the sent message",
   "source": "https://basecamp.com/features (Campfire chats for quick, casual conversations)"
  },
  {
   "id": "cap-20",
   "group": "Email forwards",
   "capability": "Forward email into a project's Inbox",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "GET /inboxes/{id}/forwards.json",
    "mcp": null,
    "cli": null,
    "ui": "Project → Email forwards"
   },
   "check": "GET /forwards/{id}.json shows the forwarded email content",
   "source": "https://github.com/basecamp/bc-api (sections/inboxes.md, sections/forwards.md, sections/inbox_replies.md)"
  },
  {
   "id": "cap-21",
   "group": "Client sharing",
   "capability": "Share selected content with clients via Client Visibility mode",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "sections/client_visibility.md, sections/client_approvals.md, sections/client_correspondences.md, sections/client_replies.md",
    "mcp": null,
    "cli": null,
    "ui": "Project → Client mode toggle per item"
   },
   "check": "Client-facing URL shows only items marked client-visible; GET client_approvals.json reflects client approval/reply",
   "source": "https://basecamp.com/features (Decide what clients get to see); https://github.com/basecamp/bc-api (sections/client_visibility.md)"
  },
  {
   "id": "cap-22",
   "group": "Boosts",
   "capability": "React to posts and comments with emoji boosts",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /recordings/{id}/boosts.json (sections/boosts.md)",
    "mcp": null,
    "cli": null,
    "ui": "Any post → Boost"
   },
   "check": "GET /recordings/{id}/boosts.json includes the new boost",
   "source": "https://github.com/basecamp/bc-api (sections/boosts.md)"
  },
  {
   "id": "cap-23",
   "group": "Out of office",
   "capability": "Set an out-of-office status that pauses assignment notifications",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "sections/out_of_office.md",
    "mcp": null,
    "cli": null,
    "ui": "Account → Out of office"
   },
   "check": "GET out_of_office endpoint shows active status with date range",
   "source": "https://github.com/basecamp/bc-api (sections/out_of_office.md)"
  },
  {
   "id": "cap-24",
   "group": "Webhooks",
   "capability": "Register webhooks for project events",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /buckets/{p}/webhooks.json",
    "mcp": null,
    "cli": null,
    "ui": "Project → Webhooks settings"
   },
   "check": "Triggering an event (e.g. new to-do) posts a payload to the registered URL",
   "source": "https://github.com/basecamp/bc-api (sections/webhooks.md)"
  },
  {
   "id": "cap-25",
   "group": "Keyboard shortcuts",
   "capability": "Navigate the app via keyboard shortcuts (SHIFT jump-to)",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Any page, hold SHIFT"
   },
   "check": "Visual confirmation: shortcut letters overlay navigable elements",
   "source": "https://basecamp.com/features (Keyboard shortcuts speed everything up)"
  },
  {
   "id": "cap-26",
   "group": "AI agent access",
   "capability": "Connect an AI agent (Claude, ChatGPT, Codex, Cursor) to act in Basecamp via CLI/MCP",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": "full MCP support (coming soon per pricing page)",
    "cli": "basecamp (official CLI)",
    "ui": null
   },
   "check": "basecamp CLI command (e.g. list todos) returns live account data after `basecamp login`",
   "source": "https://basecamp.com/agents; https://basecamp.com/pricing (ChatGPT and Claude AI connectors)"
  },
  {
   "id": "cap-27",
   "group": "Calendar subscriptions",
   "capability": "Subscribe to the Basecamp calendar from external calendar apps",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Project → Schedule → Subscribe (iCal feed)"
   },
   "check": "Visual: external calendar app (e.g. Google Calendar) shows Basecamp events after subscribing",
   "source": "https://basecamp.com/features (The Basecamp Calendar for big dates)"
  },
  {
   "id": "cap-28",
   "group": "Backlinks",
   "capability": "See backlinks showing where a piece of content is referenced elsewhere",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": "sections/backlinks.md",
    "mcp": null,
    "cli": null,
    "ui": "Item page → Referenced in"
   },
   "check": "GET /recordings/{id}/backlinks.json lists referencing items",
   "source": "https://github.com/basecamp/bc-api (sections/backlinks.md)"
  },
  {
   "id": "cap-29",
   "group": "Account admin",
   "capability": "Manage account settings, people, and admin permissions",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": "sections/account.md, sections/people.md",
    "mcp": null,
    "cli": null,
    "ui": "Account → People & settings"
   },
   "check": "GET /people.json reflects an added/removed person",
   "source": "https://github.com/basecamp/bc-api (sections/account.md, sections/people.md); https://basecamp.com/pricing (Enhanced admin features)"
  },
  {
   "id": "cap-30",
   "group": "Integrations",
   "capability": "Connect 3rd-party integrations (Figma, Google Docs, Dropbox, Zapier, etc.)",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "/extras marketplace"
   },
   "check": "Visual: linked integration appears under Project → Docs & Files as a cloud file",
   "source": "https://basecamp.com/extras; https://basecamp.com/features (API, CLI, SDK, Skills, and Integrations)"
  },
  {
   "id": "cap-31",
   "group": "Developer tooling",
   "capability": "Use official SDKs (Go, Ruby, TypeScript, Swift, Kotlin) and OpenAPI spec to build custom integrations",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": "OpenAPI spec at basecamp/basecamp-sdk",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "Generated client from openapi.json successfully calls GET /projects.json",
   "source": "https://basecamp.com/agents; https://github.com/basecamp/basecamp-sdk"
  },
  {
   "id": "cap-32",
   "group": "Branding",
   "capability": "Customize account/project branding (name, logo)",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Account settings → Customize"
   },
   "check": "Visual: new logo/name appears in top nav after save",
   "source": "https://basecamp.com/features (The Project page keeps it all together)"
  }
 ],
 "attempts": [
  {
   "t": "00:56",
   "cap": "signup",
   "capability": "Sign up",
   "task": "Create free-plan account via the public sign-up form, headless POST",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST https://app.basecamp.com/signup/account (form fields from /signup/account/new?plan=free_v3) -> 302 to /[redacted]/session/launch; account id [redacted]",
   "notes": "Plain HTML form with authenticity_token; hCaptcha script is loaded on the page but no challenge was served to our signed agent. Route is the normal web form, posted without a browser."
  },
  {
   "t": "03:00",
   "cap": "verify",
   "capability": "Verify email",
   "task": "Check whether sign-up requires email verification",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "No verification mail/step after signup: 302 straight into account [redacted]; only onboarding mails arrived. Later, first password login demanded a 6-char emailed code (Launchpad \"Email verification\"), read from our inbox.",
   "notes": "Sign-up itself needs no verification; login does (email OTP), readable headless by an agent with an inbox."
  },
  {
   "t": "03:00",
   "cap": "login",
   "capability": "Log in",
   "task": "Log in to Launchpad with email+password",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "launchpad.37signals.com/bc3/signin -> /session/email_verification (6-char code mailed, subject \"Your Basecamp 5 verification code\") -> app.basecamp.com/[redacted]/",
   "notes": "No CAPTCHA shown. Login form is marked captcha_form (hCaptcha can appear)."
  },
  {
   "t": "03:00",
   "cap": "credentials",
   "capability": "Get API credentials",
   "task": "basecamp auth login --device-code (OAuth 2.1 device flow), approve code in browser",
   "route": "cli",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "CLI printed https://app.basecamp.com/oauth/device_verification?user_code=A6UZ-NPN3; approved in browser after ticking \"I started this sign-in myself\"; CLI exited 0",
   "notes": "Approval page requires a logged-in browser session; device flow is the documented headless route. RFC8414 metadata at app.basecamp.com/.well-known/oauth-authorization-server advertises device_code, client_credentials, token-exchange."
  },
  {
   "t": "03:09",
   "cap": "first_call",
   "capability": "First API call",
   "task": "List projects via CLI and raw REST",
   "route": "cli",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "basecamp projects list --json ok:true (1 project); GET https://3.basecampapi.com/[redacted]/projects.json -> 200, 0 project",
   "notes": "UA must be set."
  },
  {
   "t": "03:30",
   "cap": "cap-01",
   "capability": "Create a project",
   "task": "Create project \"AgentDrives Drive Project\" via CLI",
   "route": "cli",
   "documented": true,
   "result": "failed",
   "verified": true,
   "evidence": "basecamp projects create -> ok:false code limit_exceeded \"The project limit for this account has been reached.\" (free plan: 1 project, signup auto-creates \"My Project\")",
   "notes": "Clear, non-retryable error. Free plan allows one project and sign-up already created it."
  },
  {
   "t": "03:36",
   "cap": "cap-01",
   "capability": "Create a project",
   "task": "Trash auto-created \"My Project\" (DELETE /projects/49118664.json -> 204), then POST /projects.json",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /projects.json -> 201 id 49118698; GET /projects/49118698.json -> 200 name \"AgentDrives Drive Project\"",
   "notes": "First POST returned 507 \"project limit reached\" (free plan = 1 active project). Trashing the existing one freed the slot. 507 is an unusual status for a plan limit."
  },
  {
   "t": "03:36",
   "cap": "first_action",
   "capability": "First real action",
   "task": "Create a project",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "project 49118698 created and read back",
   "notes": ""
  },
  {
   "t": "03:48",
   "cap": "cap-02",
   "capability": "Add tools to a project",
   "task": "Enable Card Table, Automatic Check-ins and Email Forwards in the project dock",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /buckets/49118698/recordings/<tool>/position.json -> {'kanban_board': 201, 'questionnaire': 201, 'inbox': 201}; GET /projects/49118698.json dock enabled: {'kanban_board': True, 'questionnaire': True, 'inbox': True}",
   "notes": ""
  },
  {
   "t": "04:08",
   "cap": "cap-03",
   "capability": "To-do list with due dates, assignees, subtasks",
   "task": "Create list \"Launch checklist\", to-do assigned to me due 2026-10-16, with a subtask",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /todosets/10365759792/todolists.json 201 (id 10365762427); POST /todolists/10365762427/todos.json 201 (id 10365762453); POST /recordings/10365762453/subtasks.json 201; GET /todos/10365762453.json due_on 2026-10-16, assignee 53323137, parent 10365762427, subtasks_count 1",
   "notes": ""
  },
  {
   "t": "04:09",
   "cap": "cap-04",
   "capability": "Complete / reopen a to-do",
   "task": "Complete then reopen the to-do",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST completion 204 -> GET completed=True; DELETE completion 204 -> GET completed=False",
   "notes": ""
  },
  {
   "t": "04:25",
   "cap": "cap-05",
   "capability": "Post and reply to messages",
   "task": "Post \"Kickoff notes\" to message board, reply with a comment",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /message_boards/10365759783/messages.json 201 (id 10365763315); POST /recordings/10365763315/comments.json 201; GET /messages/10365763315.json subject \"Kickoff notes\"; GET comments lists the reply",
   "notes": ""
  },
  {
   "t": "04:34",
   "cap": "cap-06",
   "capability": "Card Table stages",
   "task": "Create card in Triage, move to \"In progress\"",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /card_tables/lists/10365759800/cards.json 201 (id 10365763981); POST /card_tables/cards/10365763981/moves.json column_id 10365759807 -> 204; GET /card_tables/cards/10365763981.json parent = \"In progress\"",
   "notes": ""
  },
  {
   "t": "04:34",
   "cap": "cap-07",
   "capability": "Campfire chat",
   "task": "Post a line to the project Campfire and read it back",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /chats/10365759797/lines.json 201; GET /chats/10365759797/lines.json includes \"Hello Campfire, agent here.\"",
   "notes": "Docs path is /chats/, map said /campfires/."
  },
  {
   "t": "04:34",
   "cap": "cap-08",
   "capability": "Schedule events",
   "task": "Create \"Launch day\" schedule entry",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /schedules/10365759795/entries.json 201 (id 10365764133); GET /schedule_entries/10365764133.json starts_at 2026-10-16T09:00Z ends_at 10:00Z",
   "notes": ""
  },
  {
   "t": "04:49",
   "cap": "cap-09",
   "capability": "Hill Chart",
   "task": "Track \"Launch checklist\" on the hill chart and read the dot back; move the dot",
   "route": "api",
   "documented": true,
   "result": "partial",
   "verified": true,
   "evidence": "PUT /todosets/10365759792/hills/settings.json tracked [10365762427] -> 200; GET /todosets/10365759792/hill.json shows dot \"Launch checklist\" position 0",
   "notes": "The API (and CLI hillcharts show/track/untrack) can track and read dots but documents no way to move a dot's position; that stays web-UI only."
  },
  {
   "t": "05:08",
   "cap": "cap-10",
   "capability": "Docs & Files",
   "task": "Create folder, upload notes.txt into it, create a document",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /attachments.json?name=notes.txt 201 (sgid); POST /vaults/10365759794/vaults.json 201; POST /vaults/10365766538/uploads.json 201; POST /vaults/10365766538/documents.json 201; GETs list notes.txt, \"Agent doc\", \"Agent folder\"",
   "notes": ""
  },
  {
   "t": "05:19",
   "cap": "cap-11",
   "capability": "Automatic Check-ins",
   "task": "Create daily check-in question (guessed flat body)",
   "route": "api",
   "documented": true,
   "result": "failed",
   "verified": true,
   "evidence": "POST /questionnaires/{Q}/questions.json with flat {title,schedule:{hour,minute}} -> 422 {\"error\":\"Unprocessable Entity\"} (no field detail)",
   "notes": "My mistake: docs require nested question[...] and time_of_day; the 422 gives no hint which field is wrong."
  },
  {
   "t": "05:20",
   "cap": "cap-11",
   "capability": "Automatic Check-ins",
   "task": "Create daily weekday 5pm check-in question per docs",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /questionnaires/10365759815/questions.json -> 201; GET /questions/10365768097.json title \"What did you work on today?\" schedule {'frequency': 'every_day', 'days': [1, 2, 3, 4, 5], 'hour': 17, 'minute': 0, 'week_instance': None, 'week_interval': None, 'month_interval': None, 'start_date': '2026-10-02', 'duration': None, 'end_date': None}",
   "notes": "Answers only appear when the schedule fires; question setup verified, not an answer."
  },
  {
   "t": "05:29",
   "cap": "cap-12",
   "capability": "Reports & Everything views",
   "task": "Read assigned-to-me report and the Everything \"open to-dos\" view",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /reports/todos/assigned/53323137.json 200 (person + todos); GET /todos/open.json 200 grouped by bucket \"AgentDrives Drive Project\"; GET /projects/recordings.json?type=Todo 200",
   "notes": "Free plan allows only one project, so \"across projects\" is shown with a single bucket."
  },
  {
   "t": "05:38",
   "cap": "cap-13",
   "capability": "Lineup",
   "task": "Create a Lineup marker and read it back",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /lineup/markers.json 201 id 39365; GET /lineup/markers.json lists \"Agent launch marker\" 2026-10-16",
   "notes": ""
  },
  {
   "t": "05:38",
   "cap": "cap-14",
   "capability": "My assignments",
   "task": "Read my assignments",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /my/assignments.json 200 non_priorities includes to-do 10365762453 \"Write the launch post\"",
   "notes": ""
  },
  {
   "t": "05:38",
   "cap": "cap-17",
   "capability": "Search",
   "task": "Search for \"Kickoff\"",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /search.json?q=Kickoff 200 -> [\"Kickoff notes\"] (message created this drive)",
   "notes": "Indexed within ~1 minute."
  },
  {
   "t": "05:38",
   "cap": "cap-18",
   "capability": "Subscriptions",
   "task": "Unsubscribe then resubscribe to the message",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "DELETE /recordings/10365763315/subscription.json 204 -> GET subscribed false; POST 200 -> GET subscribed true, subscribers [53323137]",
   "notes": ""
  },
  {
   "t": "05:46",
   "cap": "cap-22",
   "capability": "Boosts",
   "task": "Boost the message with 🎉",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /recordings/10365763315/boosts.json 201 id 684054850; GET boosts -> [\"🎉\"]",
   "notes": "Body must be nested {\"boost\":{\"content\":...}}."
  },
  {
   "t": "05:46",
   "cap": "cap-23",
   "capability": "Out of office",
   "task": "Set out-of-office 2026-10-20..22",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /people/53323137/out_of_office.json 200; GET shows enabled true, 2026-10-20..2026-10-22, back_on 2026-10-23",
   "notes": ""
  },
  {
   "t": "06:05",
   "cap": "cap-15",
   "capability": "Templates",
   "task": "Create a project template",
   "route": "api",
   "documented": true,
   "result": "plan_gated",
   "verified": true,
   "evidence": "POST /templates.json -> 507 {\"error\":\"This account's package doesn't include templates.\"}",
   "notes": "Free plan; pricing lists project templates on paid plans."
  },
  {
   "t": "06:05",
   "cap": "cap-16",
   "capability": "Time tracking",
   "task": "Log 1.5h on the to-do",
   "route": "api",
   "documented": true,
   "result": "plan_gated",
   "verified": true,
   "evidence": "POST /recordings/10365762453/timesheet/entries.json -> 403 (empty body); project timesheet_enabled false",
   "notes": "Pricing lists time tracking on paid plans; the 403 carries no message saying so."
  },
  {
   "t": "06:05",
   "cap": "cap-21",
   "capability": "Client visibility",
   "task": "Make the kickoff message client-visible",
   "route": "api",
   "documented": true,
   "result": "partial",
   "verified": true,
   "evidence": "PUT /recordings/10365763315/client_visibility.json 200; GET /messages/10365763315.json visible_to_clients true",
   "notes": "Toggle verified; the client-side view itself not observed (would need a client user logged in)."
  },
  {
   "t": "06:25",
   "cap": "cap-24",
   "capability": "Webhooks",
   "task": "Register project webhook for Todo/Message to an endpoint, create a to-do, check deliveries",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /buckets/49118698/webhooks.json 201 id 2037475; new to-do 10365769955 -> GET /webhooks/2037475.json recent_deliveries: todo_created, message_shared_with_clients (each POSTed, UA \"Basecamp3 Webhook\")",
   "notes": "Payload URL was https://example.com/... (reserved domain, we had no public receiver); it answered 405, but Basecamp's own delivery log shows the payloads were sent."
  },
  {
   "t": "06:25",
   "cap": "cap-29",
   "capability": "Account admin & people",
   "task": "Rename account; add a second person (our own second inbox) to the project",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "PUT /account/name.json 200; PUT /projects/49118698/people/users.json create [the agent's inbox] -> 200 granted id 53323208; GET /projects/49118698/people.json lists both",
   "notes": "GET /people.json also lists sample-project personas (Victor Cooper etc.) and a \"GitHub\" person created by sign-up."
  },
  {
   "t": "06:25",
   "cap": "cap-19",
   "capability": "Direct pings",
   "task": "Find a documented way to send a Ping (1:1 chat) to a teammate",
   "route": "none",
   "documented": true,
   "result": "failed",
   "verified": true,
   "evidence": "bc3-api sections/ (71 files) has no pings/circles section; basecamp commands --json has no ping command (only \"pingable\" field)",
   "notes": "Pings are not exposed on the documented API/CLI; web UI only."
  },
  {
   "t": "06:37",
   "cap": "cap-28",
   "capability": "Backlinks",
   "task": "Link the kickoff message from a document, read message backlinks",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "PUT /documents/10365766599.json with link -> 200; GET /recordings/10365763315/backlinks.json -> [Document 10365766599]",
   "notes": "Gotcha: PUT without \"title\" reset the document title to \"Untitled\" (PUT replaces omitted fields)."
  },
  {
   "t": "06:49",
   "cap": "cap-20",
   "capability": "Email forwards",
   "task": "Forward an email into the project inbox and read it via API",
   "route": "api",
   "documented": true,
   "result": "partial",
   "verified": true,
   "evidence": "GET /inboxes/10365759819.json 200 (forwards_count 0); GET /inboxes/10365759819/inbox_forwards.json and bucket forwards_url -> 200 []",
   "notes": "Reading forwards works, but the API response carries no forwarding e-mail address and the agent's inbox cannot send mail, so no forward was created. Map path /inboxes/{id}/forwards.json is 404; documented path is inbox_forwards.json."
  },
  {
   "t": "07:15",
   "cap": "cap-26",
   "capability": "Agent access via CLI/MCP",
   "task": "Install official CLI, list todos, post to chat; run `basecamp mcp`, tools/list, create a to-do through MCP",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "basecamp todos list --in 49118698 ok:true; basecamp chat post ok:true; basecamp mcp tools/list -> 15 tools; tools/call basecamp_todos create_todo -> id 10365775060; GET /todos/10365775060.json title \"Created via MCP\"",
   "notes": "README says sixteen tools; v0.11.0 served 15 (no basecamp_recordings). `basecamp mcp` needs BASECAMP_ACCOUNT_ID or config, else exits. Unknown action error lists valid actions: good recovery."
  },
  {
   "t": "07:43",
   "cap": "cap-31",
   "capability": "SDKs & OpenAPI",
   "task": "npm install @37signals/basecamp@0.21.0 and list projects; read openapi.json",
   "route": "sdk",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "createBasecampClient(...).projects.list -> [[49118698,\"AgentDrives Drive Project\"]]; basecamp-sdk/openapi.json is OpenAPI 3.1.0, 186 paths / 278 operations",
   "notes": "openapi.json declares no servers block. SDK README says \"no personal access token\" while the CLI README documents personal access tokens at app.basecamp.com/my/access_tokens."
  },
  {
   "t": "07:57",
   "cap": "cap-32",
   "capability": "Branding",
   "task": "Rename account and upload account logo",
   "route": "api",
   "documented": true,
   "result": "plan_gated",
   "verified": true,
   "evidence": "PUT /account/name.json 200 (name works); PUT /account/logo.json multipart PNG -> 403 empty body; GET /account.json subscription.logo=false on \"Basecamp Free\"",
   "notes": "Logo is a paid-plan feature (account.subscription.logo false). The 403 has no body explaining it is a plan limit, while docs say 403 means \"not an admin\"."
  },
  {
   "t": "08:23",
   "cap": "cap-27",
   "capability": "Calendar subscription",
   "task": "Get the project calendar iCal feed and read it like a calendar app would",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Calendar page -> Options menu -> \"Subscribe…\" webcal://app.basecamp.com/[redacted]/buckets/49118698/schedules/10365759795/feed/<token>.ics; GET feed -> VCALENDAR with SUMMARY:Launch day DTSTART:20261016T090000Z plus the dated to-do, subtask and card",
   "notes": "Feed URL is not exposed in the schedule API response; found only via the web UI menu. Feed token kept in secrets.env."
  },
  {
   "t": "08:51",
   "cap": "cap-09",
   "capability": "Hill Chart",
   "task": "Move the \"Launch checklist\" dot up the hill in the web UI, then read it via API",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "hill/edit page: input[range] \"Position of Launch checklist on the hill\" + ArrowRight x40, notify \"No one\", Save -> GET /todosets/10365759792/hill.json position 0 -> 18",
   "notes": "Dot is an accessible range slider, so a browser agent can move it by keyboard; the API cannot."
  },
  {
   "t": "08:51",
   "cap": "cap-25",
   "capability": "Keyboard shortcuts",
   "task": "Not tested: visual UI convenience with no agent-relevant surface",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "",
   "notes": "UI-only; the jump menu hint \"Press SHIFT J\" was visible on Home."
  },
  {
   "t": "08:51",
   "cap": "cap-30",
   "capability": "Third-party integrations",
   "task": "Not tested: connecting Figma/Dropbox/Zapier needs accounts at those third parties",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "basecamp.com/extras lists third-party integrations; no Basecamp API to connect them",
   "notes": ""
  },
  {
   "t": "10:01",
   "cap": "pay",
   "capability": "Pay step",
   "task": "Look for an agent payment rail or billing API; inspect how an upgrade is bought",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "No 402 anywhere: unauth API -> 401 WWW-Authenticate Bearer resource_metadata=...; x402./mpp./agents.basecamp.com have no DNS; /.well-known/ucp, /auth.md, /skill.md 404 HTML; not in x402 Bazaar, mpp.dev/api/services or projects.dev; bc3-api has no billing section; CLI/MCP have no billing tools. Upgrade = in-app page app.basecamp.com/[redacted]/account/plans/210/edit: card number/MM-YY/CVV + billing address, \"Buy Basecamp\" ($59/mo Studio); no third-party iframe seen.",
   "notes": "Not submitted (no card, never pay). Paid-plan trial sign-up (plan=pro_v1) uses the same form as free, no card fields."
  },
  {
   "t": "12:04",
   "cap": "credentials",
   "capability": "Get API credentials (second account)",
   "task": "Use the first device-flow token on a second account (no-card Pro trial) created later under the same login",
   "route": "api",
   "documented": true,
   "result": "failed",
   "verified": true,
   "evidence": "Token from first approval -> GET https://3.basecampapi.com/[redacted]/account.json 403 (also after `basecamp auth refresh`); a second device-flow approval choosing account 2227337 works, and that token then gets 403 on the first account",
   "notes": "Approval page says the CLI gets access \"to all Basecamp accounts you belong to: including ones you join later\"; in practice each token reached only the account picked on the approval page."
  },
  {
   "t": "12:37",
   "cap": "cap-15",
   "capability": "Templates",
   "task": "On the no-card Pro trial: create template, build a project from it",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /templates.json 201 id 49118850; POST /templates/49118850/project_constructions.json 201 (pending) -> GET construction status completed, project 49118852 \"From template\"; GET /projects/49118852.json 200",
   "notes": "Account [redacted] is a no-card 30-day Pro trial; on Free the same call is 507 \"package doesn't include templates\".",
   "plan": "no-card trial"
  },
  {
   "t": "12:37",
   "cap": "cap-16",
   "capability": "Time tracking",
   "task": "On the no-card Pro trial: log 1.5h on a to-do",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /recordings/<todo>/timesheet/entries.json 201 id 10365797808; GET /timesheet_entries/10365797808.json hours 1.5 date 2026-10-02",
   "notes": "Free plan: 403 with empty body.",
   "plan": "no-card trial"
  },
  {
   "t": "12:46",
   "cap": "cap-32",
   "capability": "Branding",
   "task": "On the no-card Pro trial: upload account logo",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "PUT /account/logo.json multipart PNG -> 200 (docs say 204); GET /account.json logo.url present",
   "notes": "Free plan: 403.",
   "plan": "no-card trial"
  },
  {
   "t": "13:17",
   "cap": "cancel",
   "capability": "Cancel trial",
   "task": "Cancel the no-card Pro trial account (no headless route exists: no billing endpoint in API/CLI/MCP)",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Adminland -> \"Cancel this account\" app.basecamp.com/[redacted]/account/cancellation/new -> \"Yes, cancel my account\" -> basecamp.com/cancel \"Your account has been canceled\"; GET /[redacted]/account.json -> 404",
   "notes": "One-click, no retention flow, no support mail. Data deleted within 30 days."
  },
  {
   "t": "14:08",
   "cap": "delete",
   "capability": "Delete account and data",
   "task": "Delete both accounts and our created data; then try to delete the Basecamp ID (login)",
   "route": "browser",
   "documented": true,
   "result": "partial",
   "verified": true,
   "evidence": "API: DELETE webhook/marker/out_of_office/boost/project all 204, GET /projects.json -> [], GET /webhooks/2037475.json 404. Accounts: Adminland \"Cancel this account\" for [redacted] and [redacted] -> \"Your account has been canceled\", GET account.json -> 404 for both. Launchpad then says \"You're not part of any accounts\" and identity/edit offers no delete option.",
   "notes": "No API/CLI route to cancel or delete an account (bc3-api account.md has only name/logo). Account data deleted within 30 days per the cancel page; the Basecamp ID itself stays, with no self-serve delete seen."
  },
  {
   "t": "14:26",
   "cap": "docs",
   "capability": "Find docs",
   "task": "Locate API, CLI, SDK, MCP, OAuth docs",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "basecamp.com/agents links basecamp-cli (CLI + skill + `basecamp mcp`), basecamp-sdk (Go/Ruby/TS/Swift/Kotlin/Python/Rust dirs, openapi.json 3.1 with 278 ops), bc3-api (71 markdown sections); RFC 8414/9728 metadata at app.basecamp.com and 3.basecampapi.com; no llms.txt (basecamp.com/llms.txt -> 404 text/html)",
   "notes": ""
  }
 ],
 "stale": false,
 "icon": "/logos/basecamp.png",
 "monitored": false,
 "verdict": "Gets in on its own at L4 · Runs on its own: a plain form post signed up free, and no checkpoint stopped our agent. Browser steps stayed limited to the human parts: typing an emailed login code and approving the OAuth device code, which needs a logged-in session. From there the official CLI and the REST API covered the core work, from listing projects to creating one; the built-in MCP server is documented but wasn't shown doing the work. Paying still means filling a card in on an in-app plans page, and cancelling is one button with no retention flow: both web-only, and the trial plan our agent used needed no card at all.",
 "page": "https://agentdrives.com/tools/basecamp?via=api"
}