Basecamp API

Introduction

The Basecamp 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. In other words, we've tried to make the API follow the REST principles as much as we can.

Be sure to set the "Content-Type" header in your requests to "application/xml" (or "application/x-yaml" if you use YAML requests), which will identify the format of the data being sent. Also, you must set the "Accept" header to "application/xml", so that Basecamp will send you XML in reply, instead of HTML. Example with Curl:

curl -H 'Accept: application/xml' -H 'Content-Type: application/xml' \
  -d '<request>...</request>' http://url

Authentication is managed using HTTP authentication (only "Basic" is supported right now). Every request must include the Authorization HTTP header.

Here's an example using curl:

curl -H 'Accept: application/xml' -H 'Content-Type: application/xml' \
-u hoodlum:up2n0g00d -d '<request>...</request>' http://url

The above will return an XML-formatted response, if it succeeds. (You can look at the Ruby wrapper for more inspiration.)

If a request fails, the error information is returned with the HTTP status code. For instance, if a requested record could not be found, the HTTP response might look something like:

HTTP/1.1 404 The record could not be found
Date: Thu, 16 Mar 2006 17:41:40 GMT
...

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 use a 200 status code.

SSL Note: A request made against an account that has SSL turned on will get a redirect answer back. Be sure to call over https for an account that requires that.

In the documentation that follows, the following notation is used:

Attaching Files via the API

Some operations, like creating messages or comments, or updating existing messages or comments, allow you to attach a file to the record. To do this via the API, you need to send a POST request to the "/upload" URI, with the HTTP Accept header set to 'application/xml'. The body of the request should be the content of the file you want to attach:

POST /upload HTTP/1.0
Accept: application/xml
Content-Type: application/octet-stream
Content-Length: 23123

... (file contents go here)

If the upload succeeds, you'll get an XML response back, telling you the ID of your upload. (Your upload is not yet associated with any record, and if you do not do anything with it, it will be deleted sometime within the next 30 minutes.)

HTTP/1.0 200 OK
Content-Type: application/xml

<?xml version="1.0" encoding="UTF-8"?>
<upload><id>441b2cec.eve.21267</id></upload>

Armed with the ID, your next step is to attach the file to a record. Using the "create message" action, for instance, you pass an array of attachment data in. Assuming you had two files you wanted to attach (which you had previously uploaded, as described), your attachment data would look something like this (formatted as XML):

<attachments>
  <name>A pretty sunset</name>
  <file>
    <file>441b2cec.eve.21267</file>
    <content-type>image/jpg</content-type>
    <original-filename>sunset.jpg</original-filename>
  </file>
</attachments>
<attachments>
  <name>The ocean</name>
  <file>
    <file>441b2fff.log.21285</file>
    <content-type>image/png</content-type>
    <original-filename>ocean.png</original-filename>
  </file>
</attachments>

The Ruby wrapper implements this conversion for you--you can look at that implementation for inspiration, if you'd like.