Tempo API Reference
We have exposed an API so that anyone who is so inclined can create alternative interfaces to Tempo or integrate Tempo with an external service. This document describes how to connect to the API and what resources and methods are available.
Requirements
- Since the API provides and expects XML data, you must supply the headers ‘Accepts: application/xml’ and ‘Content-Type: application/xml’ with each request.
- Every request must be authenticated over HTTP Basic Authentication. This simply means providing your Tempo login and password along with each request.
curl -X GET -H 'Accept: application/xml' -H 'Content-Type: application/xml' \ --user mylogin:mypassword https://app.keeptempo.com/entries
Since all Tempo accounts support SSL, it would be prudent of you to connect using https when accessing the API to protect your password from prying eyes.
RESTful Resources
All end-points in our API are REST-style resources, supporting the usual set of GET, PUT, POST and DELETE operations at RESTful URLs. Currently there are only two resources available, Entries and Projects, described below.
Resource: Entries
This is what a time entry looks like when rendered in XML by the API:
<entry> <command nil="true"></command> <created-at type="datetime">2008-03-31T15:06:46-04:00</created-at> <creator-id type="integer">2048</creator-id> <hours type="decimal">5.0</hours> <id type="integer">8192</id> <is-locked type="boolean">true</is-locked> <is-timing type="boolean" nil="true"></is-timing> <notes>client meeting in NYC to discuss project requirements</notes> <occurred-on type="datetime">2008-03-31T00:00:00-04:00</occurred-on> <project-id type="integer">4096</project-id> <source>twitter</source> <start-at type="datetime" nil="true"></start-at> <stop-at type="datetime" nil="true"></stop-at> <updated-at type="datetime">2008-06-09T13:31:06-04:00</updated-at> <user-id type="integer">2048</user-id> <tag-s>meetings discovery</tag-s> </entry>
Not all fields may be updated directly; these are: :created_at, :creator_id, :id, :is_locked, :is_timing, :source, :start_at, :stop_at, :updated_at
Thus, when you want to create a new entry, you might supply a piece of XML like this:
<entry> <hours type="decimal">5.0</hours> <notes>client meeting in NYC to discuss project requirements</notes> <project-id type="integer">4096</project-id> <tag-s>meetings discovery</tag-s> </entry>
Here’s how we’d post it using curl, and the response we get:
$ curl -X POST -T entry-sample.xml -H 'Accept: application/xml' \ -H 'Content-Type: application/xml' --user billy:sekrit https://app.keeptempo.com/entries
The API will return the new entry to you as XML, or you’ll get an error response if a field was missing or incorrect:
<?xml version="1.0" encoding="UTF-8"?> <errors> <error>Project can't be blank</error> </errors>
Available URIs and methods
- https://app.keeptempo.com/entries [GET, PUT, POST]
- https://app.keeptempo.com/entries/new [GET]
- https://app.keeptempo.com/entries/search [POST]
- https://app.keeptempo.com/entries/:id [GET, PUT, DELETE]
- https://app.keeptempo.com/entries/:id;edit [GET]
- https://app.keeptempo.com/entries/:id/lock [POST]
- https://app.keeptempo.com/entries/:id/unlock [POST]
- https://app.keeptempo.com/entries/:id/start [POST]
- https://app.keeptempo.com/entries/:id/stop [POST]
Special Fields / Tricks
Hours:Start & Stop:If you don’t supply the hours with an entry, you create a new entry that has zero hours to start with, and a timer running. Sending an otherwise blank entry with
stop or starting another timer entry will stop the previous timer.
Entries & Search:The start and stop methods affect whether or not an entry is timing. So a request to /entries/5/start would cause that entry to start timing, and sending a request to /entries/5/stop would halt the timer. Note that only one timer can be running at any time, so starting a timer on one entry stops any currently running timer on another entry. Timers can be re-started, and when stopped the time is added to any time already on the entry. Read more about timers here.
When the /entries method is called via GET, a list of entries is returned for the default ‘context’ of a new session in Tempo. The basic gist here is that the entries you’ll get back from calling GET on /entries will just be for the last week, and just for the current user. As a user normally interacts with Tempo, she clicks on projects, users and tags she is interested in reporting on, and often changes the date range, too. For a full discussion of how to search entries and change the context using the API, please see the search section below.
Resource: Projects
This is what a basic Tempo project looks like when requested from the API and rendered in XML:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<basecamp-id nil="true"></basecamp-id>
<created-at type="datetime">2008-03-31T10:03:32-04:00</created-at>
<creator-id type="integer">1</creator-id>
<estimated-hours type="decimal" nil="true"></estimated-hours>
<id type="integer">1</id>
<is-active type="boolean">true</is-active>
<name>Personal</name>
<updated-at type="datetime">2008-03-31T10:03:32-04:00</updated-at>
<users type="array">
<user>
<email>billy@tankcrash.com</email>
<id type="integer">1</id>
<login>billy</login>
<name>Billy Gray</name>
</user>
</users>
</project>
Not all fields may be updated directly; these are: :basecamp_id, :created_at, :creator_id, :id, :updated_at
The only required field when creating a project is :name. The project’s users are included for your convenience, as we have not exposed a users resource in the API just yet.
Thus, to create a new project, you could use an XML document like this:
<?xml version="1.0" encoding="UTF-8"?> <project> <name>New Project</name> </project>
Available URIs and methods
- https://app.keeptempo.com/projects [GET, PUT, POST]
- https://app.keeptempo.com/projects/new [GET]
- https://app.keeptempo.com/projects/:id [GET, PUT, DELETE]
- https://app.keeptempo.com/projects/:id;edit [GET]
Note: The management of user assignments to projects and managerial delegation is not available through the API at this time.
Searching Entries via Context
POST https://app.keeptempo.com/entries/search
When requesting a set of entries from Tempo via search, you must provide a Context XML document. This is basically a set of parameters telling Tempo which entries you want. It allows you to specify which users to look at, projects, tags, and the date range. Here’s a full sample of the options:
<?xml version="1.0" encoding="UTF-8"?>
<context>
<start-date>2008-01-01</start-date>
<end-date>2008-06-01</end-date>
<project-ids type="array">
<project-id type="integer">1024</project-id>
<project-id type="integer">2048</project-id>
<project-id type="integer">8192</project-id>
</project-ids>
<user-ids type="array">
<user-id type="integer">1024</user-id>
<user-id type="integer">2048</user-id>
</user-ids>
<tags type="array">
<tag>tempo</tag>
<tag>support</tag>
</tags>
</context>
Here’s an example of how you’d execute the search using curl, assuming you saved your XML in a file called ‘context.xml’:
curl -k -X POST -T context.xml -H 'Content-Type:application/xml' \ -H 'Accept:application/xml' --user login:password \ https://app.keeptempo.com/entries/search
