API Documentation

Overview
Time Tracking

Extended REST API
Clients
Projects
Tasks
People
Expenses
Expense Tracking
User Assignment
Task Assignment
Reports
Invoices
Invoice Messages
Invoice Payments
Invoice Categories


Questions?
Email support@getharvest.com

Time Tracking API

The Time tracking API allows you to access and manipulate time entries in similar fashion to using the daily timesheet view. This allows developers to create lightweight clients or widgets to track time beyond directly interacting with Harvest through the web browser.


Retrieving entries and projects/tasks for a day

GET /daily

Retrieves entries for the today paired with the projects and tasks that can be added to the timesheet by the requesting user.

GET /daily/#{day_of_the_year}/#{year}

Optionally you may ask for entries for a given day by passing in date composed by the year and the day of the year (1..366).

HTTP Response: 200 Success
<?xml version="1.0" encoding="UTF-8"?>
<daily>
  <for_day type="date">Wed, 18 Oct 2006</for_day>
  <day_entries>
    <day_entry>
      <id type="integer">195168</id>
      <client>Iridesco</client>
      <project>Harvest</project>
      <task>Backend Programming</task>
      <!-- Includes running timer if any -->
      <hours type="float">2.06</hours>
      <notes>Test api support</notes>
      <!-- OPTIONAL returned only if a timer is running -->
      <timer_started_at type="datetime">
        Wed, 18 Oct 2006 09:53:06 -0000
      </timer_started_at>
    </day_entry>
    <day_entry>
      ...
    </day_entry>
  </day_entries>
  <!-- These are the project-task combinations that can be added to
  the timesheet. Not present in readonly timesheets or for users
  without assigned projects. -->
  <projects>
    <project>
      <name>Click and Type</name>
      <id type="integer">3</id>
      <client>AFS</client>
      <tasks>
        <task>
          <name>Security support</name>
          <id type="integer">14</id>
          <billable type="boolean">true</billable>
        </task>
        <task>
          ...
        </task>
      </tasks>
    </project>
    <project>
      ...
    </project>
  </projects>
</daily>


Toggling a timer

GET /daily/timer/#{day_entry_id}

Starts and stops a timer for a selected entry.

HTTP Response: 200 Success
<?xml version="1.0" encoding="UTF-8"?>
<timer>
  <!-- day_entry with toggled timer -->
  <day_entry>
    <id type="integer">195168</id>
    <client>Iridesco</client>
    <project>Harvest</project>
    <task>Backend Programming</task>
    <hours>2.06</hours>
    <notes>Test api support</notes>
    <!-- OPTIONAL returned if the timer was started -->
    <timer_started_at type="datetime">
      Wed, 18 Oct 2006 10:45:07 +0000
    </timer_started_at>
  </day_entry>
  <!-- OPTIONAL if a timer for another day_entry was stopped by side
  effect, returns a confirmed value for the timer. Protects against
  different clock rates on the client side. -->
  <hours_for_previously_running_timer type="float">
    0.87
  </hours_for_previously_running_timer>
</timer>


Creating an entry

POST /daily/add

Create an entry on the daily screen

HTTP Response: 201 Created

You need to POST the following:

<request>
  <notes>Test api support</notes>
  <hours>3</hours>
  <project_id type="integer">3</project_id>
  <task_id type="integer">14</task_id>
  <spent_at type="date">Tue, 17 Oct 2006</spent_at>
</request>

Note: you can transmit a blank string as hours if you want to start
a timer against the new day_entry record. For example: <hours> </hours>

You'll get the following reply:

<?xml version="1.0" encoding="UTF-8"?>
<timer>
  <!-- new entry -->
  <day_entry>
    <id type="integer">195168</id>
    <client>Iridesco</client>
    <project>Harvest</project>
    <task>Backend Programming</task>
    <hours>0.00</hours>
    <notes>Test api support</notes>

    <!-- OPTIONAL returned only if a timer was started -->
    <timer_started_at type="datetime">
      Wed, 17 Oct 2006 10:45:07 +0000
    </timer_started_at>
  </day_entry>

  <!-- OPTIONAL returned only if a timer for another -->
  <!--          day_entry was stopped as a result    -->
  <hours_for_previously_running_timer type="float">
    0.87
  </hours_for_previously_running_timer>
</timer>


Deleting an entry

DELETE /daily/delete/#{day_entry_id}

Deletes a day entry.

HTTP Response: 200 Success


Updating an entry

POST /daily/update/#{day_entry_id}

Updates the note, effort, project or task for a day entry. All sensible values are overwritten for the day entry with the data provided in your request.

HTTP Response: 200 Success

You need to POST the following:

<request>
  <notes>New notes</notes>
  <hours>1.07</hours>
  <project_id>52234</project_id>
  <task_id>67567</task_id>
</request>