Can an AI agent use Basecamp?
As of 2 Oct 2026, an AI agent gets into Basecamp on its own and does 100% of the core work.
- Find: Some docs for agents: An OpenAPI and an MCP server.
- Access: Sign-up in a browser.
- Use: 100% of the work.
- Pay: Reaches the checkout: Stopped at the card form.
- Leave: Leaves on its own: Cancels on its own, deletes its account.
To reach L5 · Autonomous: pay without a person.
What the levels meanDriven 2 Oct 2026Same level in 2 drives in a rowRules of 15 Oct 2026Claim this page
Written and checked by our agents from this drive's record. How we write.
Who gets in
- Agents on a serverGet in on their own.
- Signed agentsThe sign-up page opens.
- Agents in a person's browserNot measured yet.
Sign-up page checked 13 Oct 2026. Signed agents: the ones Cloudflare verifies. Where agents come from
What an agent can do in Basecamp.
On its own
- 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
2 more
- Try paid features for free for 30 days without a credit card
- Delete everything it created when done
What it can't, and why
- Get its first API key without a browserA one-time login code must be approved on a logged-in web page (the agent did this in its browser)
- Send a direct one-to-one chat messageThat feature has no programmatic way to trigger it
- Buy a paid plan or cancel without a browserPayment and cancellation only exist as web pages, no API (the agent cancelled in its browser)
1 more
- Delete its own login identityNo self-service option exists for that
Can an AI agent sign up for Basecamp on its own?
Yes, over the API, without a browser. 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.
Does Basecamp have an MCP server, and can an agent connect to it?
Yes. Basecamp has an official MCP server. The server runs on the agent's own machine.
A new agent can get in on its own: in the drive of 2 Oct 2026, our agent signed up, verified and got its key without a person. Through the MCP server, 1 of our agent's 1 attempt worked.
What the drive found
APIOpenAPIMCP · officialCLISDK–llms.txtWebhooks–SandboxHow does an AI agent get a Basecamp API key?
In the drive of 2 Oct 2026, our agent got its Basecamp API key in a browser, without a person. 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.
Can an AI agent delete its Basecamp account?
Yes, in a browser, without a human. 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.
Can an AI agent pay for Basecamp?
Reaches the checkout: stopped at the card form.
No card needed to start.
What would let agents pay on their own
- Accept x402 or MPP on your API. 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.Step-by-step guide
- List your plans on Stripe Projects. Agents buy a plan with `stripe projects add`, paid with a token under a spend cap the owner sets (projects.dev).Step-by-step guide
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.
From the drive of 2 Oct 2026.
For the team behind Basecamp.
Agents get through Basecamp today. The fixes that keep it that way, highest impact first.
The fixes, highest impact first
- Let agents get a token without a browserStep-by-step guide
- Make the device-approval account scope match its wordingStep-by-step guide
- Add a billing and cancellation APIStep-by-step guide
3 more fixes
- 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 Step-by-step guide
- Claim it free and reply next to the result.
- A Drive, $49: your private report, with where agents stop, the evidence and the fixes that move your level.
- Fixed something? Order a Drive ($49) any time, or the Monthly drive ($29/month).
Details
Your API, MCP server or CLI is the product? An Audit ($299) also checks every documented route, MCP tool and CLI command against your docs. Compare plans.
Already claimed it? Open it in your dashboard.
Rather not be driven? Block AgentDrivesAgent in robots.txt or write to us. We stop driving it ourselves; this page stays, with its date.
Embed the badge on your site
Behind the level.
The part scores and the measures behind them.
Part scores and the measures · level history · paid plans
Part scores
Agent-ready setup
- llms.txt: not found
- OpenAPI: found
- MCP server: found
- CLI: found
Not measured in this drive: Holds up, Docs match (part of an Audit).
The measures
- Work done100
- Reliability78
- Crash test–
Level history
- 1 Oct 2026L4Runs on its own
- 2 Oct 2026L4Runs on its own
Needs a paid plan
Not counted in the level. Our drive used free plan (core); no-card 30-day Pro trial for templates, time tracking and logo.
| Capability | Plan |
|---|---|
| Templates | Freelancer/Studio/Pro (no-card trial worked) |
| Time tracking | paid (no-card trial worked) |
| Branding (logo) | paid (no-card trial worked) |
For agents and builders.
The drive as data, every checkpoint and all 49 attempts.
How an agent connects · 8 tips
/api/tools/basecamp.json/tools/basecamp.mdMCP get_tool {"slug":"basecamp"}
- 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.
Every checkpoint, in detail · 9 checkpoints
- DocsHeadlessbasecamp.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.
- Sign upHeadlessThe 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.
- VerifyIn a browserSign-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.
- KeyIn a browserDocumented 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.
- First callHeadlessbasecamp projects list --json and GET https://3.basecampapi.com/[redacted]/projects.json both 200.
- First actionHeadlessPOST /projects.json created a project (after trashing the auto-made one: Free allows 1 project; the limit returns 507).
- PayIn a browserNo 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.
- CancelIn a browserAdminland -> '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.
- DeleteIn a browserRecords 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.
The attempt log · 49 attempts
| Capability | Route | Result | Evidence |
|---|---|---|---|
| Sign up: Create free-plan account via the public sign-up form, headless POST | api | done ✓ | POST https://app.basecamp.com/signup/account (form fields from /signup/account/new?plan=free_v3) -> 302 to /[redacted]/session/launch; account id [redacted] |
| Verify email: Check whether sign-up requires email verification | api | done ✓ | 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. |
| Log in: Log in to Launchpad with email+password | browser | done ✓ | launchpad.37signals.com/bc3/signin -> /session/email_verification (6-char code mailed, subject "Your Basecamp 5 verification code") -> app.basecamp.com/[redacted]/ |
| Get API credentials: basecamp auth login --device-code (OAuth 2.1 device flow), approve code in browser | cli | done ✓ | 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 |
| First API call: List projects via CLI and raw REST | cli | done ✓ | basecamp projects list --json ok:true (1 project); GET https://3.basecampapi.com/[redacted]/projects.json -> 200, 0 project |
| Create a project: Create project "AgentDrives Drive Project" via CLI | cli | failed ✓ | 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") |
| Create a project: Trash auto-created "My Project" (DELETE /projects/49118664.json -> 204), then POST /projects.json | api | done ✓ | POST /projects.json -> 201 id 49118698; GET /projects/49118698.json -> 200 name "AgentDrives Drive Project" |
| First real action: Create a project | api | done ✓ | project 49118698 created and read back |
| Add tools to a project: Enable Card Table, Automatic Check-ins and Email Forwards in the project dock | api | done ✓ | 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} |
| To-do list with due dates, assignees, subtasks: Create list "Launch checklist", to-do assigned to me due 2026-10-16, with a subtask | api | done ✓ | 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 |
| Complete / reopen a to-do: Complete then reopen the to-do | api | done ✓ | POST completion 204 -> GET completed=True; DELETE completion 204 -> GET completed=False |
| Post and reply to messages: Post "Kickoff notes" to message board, reply with a comment | api | done ✓ | 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 |
| Card Table stages: Create card in Triage, move to "In progress" | api | done ✓ | 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" |
| Campfire chat: Post a line to the project Campfire and read it back | api | done ✓ | POST /chats/10365759797/lines.json 201; GET /chats/10365759797/lines.json includes "Hello Campfire, agent here." |
| Schedule events: Create "Launch day" schedule entry | api | done ✓ | POST /schedules/10365759795/entries.json 201 (id 10365764133); GET /schedule_entries/10365764133.json starts_at 2026-10-16T09:00Z ends_at 10:00Z |
| Hill Chart: Track "Launch checklist" on the hill chart and read the dot back; move the dot | api | partial ✓ | PUT /todosets/10365759792/hills/settings.json tracked [10365762427] -> 200; GET /todosets/10365759792/hill.json shows dot "Launch checklist" position 0 |
| Docs & Files: Create folder, upload notes.txt into it, create a document | api | done ✓ | 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" |
| Automatic Check-ins: Create daily check-in question (guessed flat body) | api | failed ✓ | POST /questionnaires/{Q}/questions.json with flat {title,schedule:{hour,minute}} -> 422 {"error":"Unprocessable Entity"} (no field detail) |
| Automatic Check-ins: Create daily weekday 5pm check-in question per docs | api | done ✓ | 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} |
| Reports & Everything views: Read assigned-to-me report and the Everything "open to-dos" view | api | done ✓ | 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 |
| Lineup: Create a Lineup marker and read it back | api | done ✓ | POST /lineup/markers.json 201 id 39365; GET /lineup/markers.json lists "Agent launch marker" 2026-10-16 |
| My assignments: Read my assignments | api | done ✓ | GET /my/assignments.json 200 non_priorities includes to-do 10365762453 "Write the launch post" |
| Search: Search for "Kickoff" | api | done ✓ | GET /search.json?q=Kickoff 200 -> ["Kickoff notes"] (message created this drive) |
| Subscriptions: Unsubscribe then resubscribe to the message | api | done ✓ | DELETE /recordings/10365763315/subscription.json 204 -> GET subscribed false; POST 200 -> GET subscribed true, subscribers [53323137] |
| Boosts: Boost the message with 🎉 | api | done ✓ | POST /recordings/10365763315/boosts.json 201 id 684054850; GET boosts -> ["🎉"] |
| Out of office: Set out-of-office 2026-10-20..22 | api | done ✓ | POST /people/53323137/out_of_office.json 200; GET shows enabled true, 2026-10-20..2026-10-22, back_on 2026-10-23 |
| Templates: Create a project template | api | plan_gated ✓ | POST /templates.json -> 507 {"error":"This account's package doesn't include templates."} |
| Time tracking: Log 1.5h on the to-do | api | plan_gated ✓ | POST /recordings/10365762453/timesheet/entries.json -> 403 (empty body); project timesheet_enabled false |
| Client visibility: Make the kickoff message client-visible | api | partial ✓ | PUT /recordings/10365763315/client_visibility.json 200; GET /messages/10365763315.json visible_to_clients true |
| Webhooks: Register project webhook for Todo/Message to an endpoint, create a to-do, check deliveries | api | done ✓ | 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") |
| Account admin & people: Rename account; add a second person (our own second inbox) to the project | api | done ✓ | 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 |
| Direct pings: Find a documented way to send a Ping (1:1 chat) to a teammate | none | failed ✓ | bc3-api sections/ (71 files) has no pings/circles section; basecamp commands --json has no ping command (only "pingable" field) |
| Backlinks: Link the kickoff message from a document, read message backlinks | api | done ✓ | PUT /documents/10365766599.json with link -> 200; GET /recordings/10365763315/backlinks.json -> [Document 10365766599] |
| Email forwards: Forward an email into the project inbox and read it via API | api | partial ✓ | GET /inboxes/10365759819.json 200 (forwards_count 0); GET /inboxes/10365759819/inbox_forwards.json and bucket forwards_url -> 200 [] |
| Agent access via CLI/MCP: Install official CLI, list todos, post to chat; run `basecamp mcp`, tools/list, create a to-do through MCP | mcp | done ✓ | 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" |
| SDKs & OpenAPI: npm install @37signals/basecamp@0.21.0 and list projects; read openapi.json | sdk | done ✓ | createBasecampClient(...).projects.list -> [[49118698,"AgentDrives Drive Project"]]; basecamp-sdk/openapi.json is OpenAPI 3.1.0, 186 paths / 278 operations |
| Branding: Rename account and upload account logo | api | plan_gated ✓ | 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" |
| Calendar subscription: Get the project calendar iCal feed and read it like a calendar app would | browser | done ✓ | 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 |
| Hill Chart: Move the "Launch checklist" dot up the hill in the web UI, then read it via API | browser | done ✓ | 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 |
| Keyboard shortcuts: Not tested: visual UI convenience with no agent-relevant surface | none | skipped | |
| Third-party integrations: Not tested: connecting Figma/Dropbox/Zapier needs accounts at those third parties | none | skipped | basecamp.com/extras lists third-party integrations; no Basecamp API to connect them |
| Pay step: Look for an agent payment rail or billing API; inspect how an upgrade is bought | browser | done ✓ | 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. |
| Get API credentials (second account): Use the first device-flow token on a second account (no-card Pro trial) created later under the same login | api | failed ✓ | 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 |
| Templates: On the no-card Pro trial: create template, build a project from it | api | done ✓ | 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 |
| Time tracking: On the no-card Pro trial: log 1.5h on a to-do | api | done ✓ | POST /recordings/<todo>/timesheet/entries.json 201 id 10365797808; GET /timesheet_entries/10365797808.json hours 1.5 date 2026-10-02 |
| Branding: On the no-card Pro trial: upload account logo | api | done ✓ | PUT /account/logo.json multipart PNG -> 200 (docs say 204); GET /account.json logo.url present |
| Cancel trial: Cancel the no-card Pro trial account (no headless route exists: no billing endpoint in API/CLI/MCP) | browser | done ✓ | 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 |
| Delete account and data: Delete both accounts and our created data; then try to delete the Basecamp ID (login) | browser | partial ✓ | 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. |
| Find docs: Locate API, CLI, SDK, MCP, OAuth docs | api | done ✓ | 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) |
Also in Project management.
PlaneL4Gets in on its ownBasecamp vs Plane
GitHubL4Gets in on its ownBasecamp vs GitHub
ShortcutL4Gets in on its ownBasecamp vs Shortcut
monday.comL3Gets in on its ownBasecamp vs monday.com