A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.
The Basecamp API is how an app or AI agent works with a Basecamp account: listing and creating projects, adding and completing to-dos, posting messages and documents, and sending lines into Campfire chats. Access is granted through a single OAuth token tied to one account, and that token can read and write everywhere the person who authorized it belongs, since Basecamp has no granular per-endpoint permissions. Basecamp can also push events to a webhook when something happens in a project.
How an app or AI agent connects to Basecamp determines what it can reach. Access runs through an OAuth 2.0 token tied to one account, and that token can read and write everywhere the authorizing person can.
The BC3 REST API answers at https://3.basecampapi.com, with every path prefixed by the account id and ending in .json. A User-Agent header that identifies the app is required, or the request is rejected.
Webhooks deliver project events to a receiver URL over HTTPS. Each webhook is created on a single project, and Basecamp retries delivery with exponential backoff when the receiver fails.
A chatbot posts lines to a Campfire using its own access key rather than an OAuth token. Its endpoint includes the project-scoped /buckets/{id}/ prefix and the chatbot key in the path.
OAuth 2.0 is the way an app or AI agent authorizes against Basecamp. A person grants access, the app receives an access token tied to one account, and that token can read and write everywhere the person can. There are no granular per-endpoint scopes.
A chatbot has its own access key instead of an OAuth token. It can only post lines into the Campfires it has been added to, and cannot reach the rest of the API.
The Basecamp API is organized around projects and the tools inside them, such as to-do lists, message boards, documents, schedules, and Campfire chats. Each project carries its own membership, and a token reaches only the projects its person belongs to.
List, read, create, and update projects, and trash a project. Each project holds a dock of enabled tools.
List and create to-do lists, list and create to-dos, and mark a to-do complete.
List, read, create, and update messages on a project's message board.
List, read, create, and update documents inside a project's vault.
List and read comments on any recording, and post a new comment.
List Campfires, read their lines, and post a new line to a Campfire chat.
Read a project's schedule and update its settings.
List all people, list people on a project, and read a person's profile.
List recordings of any type across projects, and trash or archive a single recording.
List a project's webhooks and create a new one to receive events.
Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.
| Method | Endpoint | What it does | Access | Permission | Version | |
|---|---|---|---|---|---|---|
ProjectsList, read, create, and update projects, and trash a project. Each project holds a dock of enabled tools.5 | ||||||
| GET | /projects.json | List active projects visible to the current user, newest first. A status parameter can filter for archived or trashed projects. | read | Account access | Current | |
Returns only the projects the authorizing person belongs to. Basecamp has no granular per-endpoint scopes; one OAuth token grants account-level access bounded by the person's project memberships. Acts onproject Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /projects/{id}.json | Get a single project, including a dock array of its tools and whether each is enabled. | read | Account access | Current | |
The dock holds the ids needed to reach the project's to-do set, message board, vault, schedule, and Campfire. Acts onproject Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /projects.json | Create a project. A name is required and a description is optional. Returns 507 if the account project limit is reached. | write | Account access | Current | |
Project creation is bounded by the account's plan limit, not by a separate permission. Acts onproject Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /projects/{id}.json | Update a project's name, description, schedule dates, and access policy. The name is required. | write | Account access | Current | |
Changing the access policy can admit or remove people from the whole project. Acts onproject Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /projects/{id}.json | Trash a project. Trashed projects are permanently deleted after 30 days. Returns 204 on success. | write | Account access | Current | |
This removes the entire project and every tool inside it from where people see it. Acts onproject Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
To-do lists & to-dosList and create to-do lists, list and create to-dos, and mark a to-do complete.5 | ||||||
| GET | /todosets/{id}/todolists.json | List the active to-do lists in a project's to-do set. | read | Account access | Current | |
The to-do set id comes from the project's dock. Acts onto-do list Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /todosets/{id}/todolists.json | Create a to-do list in a project's to-do set. A name is required. | write | Account access | Current | |
Fires the todolist_created webhook event on the project. Acts onto-do list Permission (capability) Account accessVersionAvailable since the API’s base version Webhook event todolist_createdRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /todolists/{id}/todos.json | List the active to-dos in a to-do list. | read | Account access | Current | |
A completed parameter can include finished to-dos. Acts onto-do Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /todolists/{id}/todos.json | Create a to-do in a to-do list. Content is required, with optional description, assignees, and due date. | write | Account access | Current | |
Assigning people notifies them. Fires the todo_created webhook event. Acts onto-do Permission (capability) Account accessVersionAvailable since the API’s base version Webhook event todo_createdRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /todos/{id}/completion.json | Mark a to-do as completed. | write | Account access | Current | |
The matching DELETE on the same path reopens the to-do. Fires the todo_completed webhook event. Acts onto-do Permission (capability) Account accessVersionAvailable since the API’s base version Webhook event todo_completedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
MessagesList, read, create, and update messages on a project's message board.4 | ||||||
| GET | /message_boards/{id}/messages.json | List the active messages on a project's message board. | read | Account access | Current | |
The message board id comes from the project's dock. Acts onmessage Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /messages/{id}.json | Get a single message by id. | read | Account access | Current | |
Reachable only when the token's person belongs to the project that holds the message. Acts onmessage Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /message_boards/{id}/messages.json | Create a message on a message board. A subject is required, with optional content and category. | write | Account access | Current | |
A posted message notifies everyone subscribed to the board. Fires the message_created webhook event. Acts onmessage Permission (capability) Account accessVersionAvailable since the API’s base version Webhook event message_createdRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /messages/{id}.json | Update a message's subject, content, or category. | write | Account access | Current | |
Editing the subject or content fires message_title_updated or message_content_updated. Acts onmessage Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
DocumentsList, read, create, and update documents inside a project's vault.3 | ||||||
| GET | /vaults/{id}/documents.json | List the active documents in a project's vault. | read | Account access | Current | |
A vault is the folder that holds a project's documents and uploads. Its id comes from the project's dock. Acts ondocument Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /vaults/{id}/documents.json | Create a document in a vault. A title and content are required. Returns 201 on success. | write | Account access | Current | |
Content is rich text and accepts the same HTML Basecamp's editor produces. Fires the document_created webhook event. Acts ondocument Permission (capability) Account accessVersionAvailable since the API’s base version Webhook event document_createdRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /documents/{id}.json | Update a document's title and content. Returns 200 on success. | write | Account access | Current | |
Editing fires document_title_updated or document_content_updated. Acts ondocument Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
CommentsList and read comments on any recording, and post a new comment.2 | ||||||
| GET | /recordings/{id}/comments.json | List the active comments on any recording, such as a message, document, or to-do. | read | Account access | Current | |
A recording is the shared base type for commentable items, so the same endpoint serves every tool. Acts oncomment Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /recordings/{id}/comments.json | Post a comment on a recording. Content is required. | write | Account access | Current | |
A posted comment notifies the people following that item. Fires the comment_created webhook event. Acts oncomment Permission (capability) Account accessVersionAvailable since the API’s base version Webhook event comment_createdRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Campfires (chats)List Campfires, read their lines, and post a new line to a Campfire chat.3 | ||||||
| GET | /chats.json | List all active Campfires, the real-time group chats, visible to the current user. | read | Account access | Current | |
Each Campfire belongs to one project the person can see. Acts oncampfire Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /chats/{id}/lines.json | List the lines, the individual chat messages, in a Campfire. | read | Account access | Current | |
Returns the recent chat history of the Campfire. Acts oncampfire line Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /chats/{id}/lines.json | Post a new line to a Campfire. Content is required. | write | Account access | Current | |
A posted line is visible to everyone in the Campfire. A separate chatbot key, not OAuth, can also post lines. Acts oncampfire line Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
SchedulesRead a project's schedule and update its settings.2 | ||||||
| GET | /schedules/{id}.json | Get a project's schedule. The schedule id comes from the project's dock. | read | Account access | Current | |
The schedule holds the project's dated entries. Acts onschedule Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /schedules/{id}.json | Update a schedule's settings, such as whether it includes due dates from to-dos, cards, and steps. | write | Account access | Current | |
The include_due_assignments parameter controls whether dated assignments appear on the schedule. Acts onschedule Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
PeopleList all people, list people on a project, and read a person's profile.3 | ||||||
| GET | /people.json | List all people visible to the current user across the account. | read | Account access | Current | |
Returns names, email addresses, titles, and avatar URLs for the people on the account. Acts onperson Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /projects/{id}/people.json | List the active people on a single project. | read | Account access | Current | |
Shows who can see and act within the project. Acts onperson Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /people/{id}.json | Get a single person's profile by id. | read | Account access | Current | |
Returns the person's name, email address, and other profile fields. Acts onperson Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
RecordingsList recordings of any type across projects, and trash or archive a single recording.3 | ||||||
| GET | /projects/recordings.json | List recordings of one type across projects, such as Todo, Message, Document, Comment, or Upload, with filters for bucket, status, and sort. | read | Account access | Current | |
A recording is the shared base type behind nearly every item in a project, so this is the cross-project way to find items of one kind. Acts onrecording Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /recordings/{id}/status/trashed.json | Trash a recording, such as a message, document, or to-do. Returns 204 on success. | write | Account access | Current | |
Removes the item from where people see it. A matching status/active call restores it. Acts onrecording Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /recordings/{id}/status/archived.json | Archive a recording. Returns 204 on success. | write | Account access | Current | |
Archiving hides the item without deleting it. A status/active call unarchives it. Acts onrecording Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
WebhooksList a project's webhooks and create a new one to receive events.2 | ||||||
| GET | /buckets/{id}/webhooks.json | List the webhooks set up on a single project. | read | Account access | Current | |
A bucket is the internal name for a project, so this lists that project's webhooks. Acts onwebhook Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /buckets/{id}/webhooks.json | Create a webhook on a project. A payload URL is required, with an optional list of event types to receive. | write | Account access | Current | |
Webhooks are created per project, not account-wide, so each project needs its own. Acts onwebhook Permission (capability) Account accessVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Basecamp can notify an app or AI agent when something happens in a project, instead of the app repeatedly asking. A webhook is created on a single project, and Basecamp posts a payload to its URL whenever a matching event fires there.
| Event | What it signals | Triggered by |
|---|---|---|
todo_created | Fires when a to-do is created in a project. | /todolists/{id}/todos.json |
todo_completed | Fires when a to-do is marked complete. | /todos/{id}/completion.json |
todolist_created | Fires when a to-do list is created in a project's to-do set. | /todosets/{id}/todolists.json |
message_created | Fires when a message is posted to a project's message board. | /message_boards/{id}/messages.json |
document_created | Fires when a document is created in a project's vault. | /vaults/{id}/documents.json |
comment_created | Fires when a comment is posted on a recording. | /recordings/{id}/comments.json |
Basecamp limits how fast an app or AI agent can call, through a request quota measured per IP address over a short window. Going over returns a 429 response with a Retry-After header that says how long to wait.
Basecamp applies several dynamic rate limits, and the one most commonly hit is 50 requests per 10 second window per IP address. Going over returns a 429 response with a Retry-After header giving the seconds to wait before the next request. Server errors in the 500 range should be retried with exponential backoff, while a 404 should not be retried automatically. Every request must carry a User-Agent header naming the app, or it is rejected with 400.
Collections use link-based pagination through a Link header, following the RFC 5988 convention, rather than page-number parameters. Basecamp uses geared pagination, where page sizes grow from 15 to 30 to 50 and then 100 or more as paging continues. An empty Link header means the last page has been reached, and an X-Total-Count header gives the total number of items.
All data is JSON with snake_case keys and no root element, and every API URL ends in .json. POST and PUT requests must send the Content-Type header application/json; charset=utf-8, or the request is rejected with 415. Rich text fields, such as message and document content, accept HTML.
The status codes an agent should handle, and what to do about each.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 400 | Bad Request | The request is malformed, most often because the required User-Agent header that identifies the app is missing. | Send a User-Agent header that names the app and includes a contact, then resend. |
| 401 | Unauthorized | Authentication is missing or the access token is invalid or expired. Tokens last two weeks. | Refresh the access token using the refresh token, then retry. |
| 403 | Forbidden | The token is valid but the person is not allowed to perform the action on this resource. | Confirm the person belongs to the project and has permission for the action. |
| 404 | Not Found | The resource does not exist, has been deleted, or the token cannot see it. Basecamp advises against automatically retrying a 404. | Confirm the path and that the person has access, and do not retry automatically. |
| 415 | Unsupported Media Type | A POST or PUT was sent without the Content-Type application/json; charset=utf-8 header. | Set the Content-Type header to application/json; charset=utf-8 and resend. |
| 429 | Too Many Requests | The rate limit was exceeded. The commonly hit limit is 50 requests per 10 second window per IP address. | Wait the number of seconds in the Retry-After header before sending the next request. |
| 507 | Insufficient Storage | Returned when creating a project would exceed the account's project limit. | Free up a project slot or upgrade the account, then retry. |
Basecamp does not use dated API versions. The current generation is the BC3 API, served without a version segment in the path, and changes ship through updates to the public documentation rather than new version strings.
The BC3 API is the current generation, serving Basecamp 3 and Basecamp 4. It uses OAuth 2.0, carries no version segment in its paths, and has no version header to pin. Changes are published as updates to the public bc3-api documentation rather than as new dated versions, so an integration tracks a single, continuously current API. The dated entries below are notable documentation updates from the public bc3-api repository.
Documentation was updated to reflect changes from the Basecamp 5 line, including bubble ups and email-address redaction.
The optional content_type parameter was documented for rich-text Campfire lines, and card steps were documented as accepting an assignee_ids array, matching to-dos and cards.
Flat resource routes were presented as the primary paths for dock tool endpoints, with the legacy /buckets/{id}/ project-scoped routes kept working alongside them.
New sections documented upload version history, card-table move endpoints, hill charts, and Campfire file uploads.
An integration tracks the single current API, with no version header to pin.
Basecamp API changelog ↗Bollard AI sits between a team's AI agents and Basecamp. Grant each agent exactly the access it needs, read or write, project area by project area, and every call is checked and logged.