Official API documentation for Basecamp Classic
Pull request Compare This branch is 6 commits behind basecamp:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Basecamp Classic API

This is the API for Basecamp Classic ( Check out the API for the all new Basecamp ( on GitHub.

The Basecamp Classic API is implemented as vanilla XML over HTTP using all four verbs (GET/POST/PUT/DELETE). Every resource, like Post, Comment, or TodoList, has their own URL and are manipulated in isolation. We've tried to make the API follow the REST principles as much as we can.

Wrappers and example code

Wrote your own API wrapper? Feel free to open a pull request and add to this list!


If you're making a private integration with Basecamp Classic for your own purposes, you can use HTTP Basic authentication. This is secure since all requests in the new Basecamp use SSL.

Your API token can be found by logging into your Basecamp Classic account, clicking on the "My Info" link in the upper-right, and then clicking the "Show your tokens" at the bottom (under "Authentication tokens").

If you're making a public integration with Basecamp Classic for others to enjoy, you can also use OAuth 2. This allows users to authorize your application to use Basecamp Classic on their behalf without having to copy/paste API tokens or touch sensitive login info.

Read the 37signals API Authentication Guide for more info on using OAuth.

Making a request

Be sure to set both the 'Content-Type' and 'Accept' headers to 'application/xml' to identify the request and response format. Example with Curl:

curl -H 'Accept: application/xml' -H 'Content-Type: application/xml' \
  -u hoodlum:up2n0g00d \
  -d '<todo-item><content>...</content></todo-item>' \

API Endpoints

(Hint: Press t to enable the file finder and type out the endpoint you need!)

Need a sample of each XML blob will look like? Check out the Data Reference.


If a request succeeds, it will return a status code in the 200 range and often, an XML-formatted response. Note that, in general, if a request causes a new record to be created (like a new message, or to-do item, etc.), the response will use the "201 Created" status. Any other successful operation (like a successful query, delete, or update) will return a 200 status code.

Rate limiting

You can perform up to 500 requests per 10 second period from the same IP address for the same account. If you exceed this limit, you'll get a 503 response for subsequent requests. Check the Retry-After header to see how many seconds to wait before trying again.

SSL Usage

A non-SSL request made against an account that has SSL enabled (and vice versa) will receive a "302 Found" response. The Location header will contain the correct URI.

If SSL is enabled for your account, ensure that you're using https. If it's not, ensure you're using http.

Documentation Conventions

To make things easier to understand, the following notation is used:

  • #{text}: Indicates text that should be replaced by your own data
  • ...: Indicates content from the response has been elided for brevity in documentation. See the list of data responses at the end of the page for a full description of the format of that response type.

Help us make it better

Please tell us how we can make this API better. If you have a specific feature request or if you found a bug, please open a support ticket. Also, feel free to fork these docs and send a pull request with improvements!

To talk with us and other developers about the API, subscribe to the 37signals-api mailing list.