API Documentation

Overview
Time Tracking

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


Questions? Contact support

Invoices

Important: this assumes invoice feature is enabled for your account.


Show recently issued invoices

GET /invoices

HTTP Response: 200 Success
<invoices type="array">
  <invoice>
    <id type="integer">8</id>
    <amount type="decimal">1155.0</amount>
    <due-amount type="decimal">0.0</due-amount>
    <due-at type="date">2008-02-06</due-at>
    <!-- human representation for due at -->
    <due-at-human-format>due upon receipt</due-at-human-format>
    <!-- invoiced period, present for generated invoices -->
    <period-end type="date" nil="true"></period-end>
    <period-start type="date" nil="true"></period-start>
    <client-id type="integer">46066</client-id>
    <!-- see  -->
    <currency>United States Dollars - USD</currency>
    <issued-at type="date">2008-02-06</issued-at>
    <notes></notes>
    <number>8008</number>
    <purchase-order></purchase-order>
    <!-- See invoice messages and invoice payments for manipulating the
    state attribute.  Direct assigment will be ignored. -->
    <state>paid</state>
    <!-- applied tax percentage, blank if not taxed -->
    <tax type="decimal" nil="true"></tax>
    <!-- applied tax 2 percentage, blank if not taxed -->
    <tax2 type="decimal" nil="true"></tax2>
    <!-- the first tax amount -->
    <tax-amount type="decimal" nil="true"></tax-amount>
    <!-- the second tax amount -->
    <tax-amount2 type="decimal" nil="true"></tax-amount2>
    <updated-at type="datetime">2008-04-09T12:07:56Z</updated-at>
    <created-at type="datetime">2008-04-09T12:07:56Z</created-at>
  </invoice>
  <!-- .... -->
</invoices>

For performance reasons line item data is not shown for this call, you'll have to use a more specific API call.


By default Harvest will display 50 records per page. You can get further pages by passing in a page parameter.

GET /invoices?page=2

HTTP Response: 200 Success

You can also query invoices by timeframe based on issue date.

GET /invoices?from=YYYYMMDD&to=YYYYMMDD

HTTP Response: 200 Success

You can filter by updated_since. To show only the invoices that have been updated since "2010-08-03 18:30", pass the UTC date time value (URL encoded).

GET /invoices?updated_since=2010-08-03+18%3A30

HTTP Response: 200 Success

Filtering by invoice state is also possible, for example this would return partially paid invoices:

GET /invoices?status=partial

HTTP Response: 200 Success

Other parameters for filtering by state are:

open
sent to the client but no payment recieved.
partial
partial payment was recorded
draft
harvest did not sent this to a client, nor recorded any payments
paid
invoice payed in full
unpaid
Macro used to return unpaid invoices
pastdue
Macro used to return past due invoices


You can also filter by client, for example to show only the invoices belonging to client with the id 23445

GET /invoices?client=23445

HTTP Response: 200 Success

All of the above filters can be combined, allowing for powerful queries into your records.

Show a particular invoice

GET /invoices/#{invoice_id}

HTTP Response: 200 Success
<invoice>
  <amount type="decimal">253.44</amount>
  <client-id type="integer">8</client-id>
  <created-at type="datetime">2008-04-09T12:07:56Z</created-at>
  <currency>United States Dollars - USD</currency>
  <due-amount type="decimal">253.44</due-amount>
  <due-at type="date">2008-02-06</due-at>
  <due-at-human-format>due upon receipt</due-at-human-format>
  <id type="integer">1421</id>
  <issued-at type="date">2008-02-06</issued-at>
  <notes>Some notes go here</notes>
  <number>82208</number>
  <period-end type="date">2008-03-31</period-end>
  <period-start type="date">2007-06-26</period-start>
  <purchase-order nil="true"></purchase-order>
  <!-- See invoice messages and invoice payments for manipulating the
   state attribute.  Direct assigment will be ignored. -->
  <state>draft</state>
  <updated-at type="datetime">2008-04-09T18:56:51Z</updated-at>
  <!-- Line items in CSV format -->
  <csv-line-items>
kind,description,quantity,unit_price,amount,taxed,taxed2,project_id
Service,Security support / Apply upgrades,0.68,80.00,54.4,true,false,3
Service,Security support / Intrusion detection,0.57,80.00,45.6,true,false,3
Service,Backend Programming / Forum admin,1.20,80.00,96.0,true,false,3
  </csv-line-items>
  <!-- applied a 10% tax on all line items marked as taxed -->
  <tax type="decimal">10</tax>
  <!-- no second tax -->
  <tax2 type="decimal" nil="true"></tax2>
  <!-- tax amount -->
  <tax-amount type="decimal">23.04</tax-amount>
  <tax2-amount type="decimal" nil="true">0</tax2-amount>
</invoice>

Create a new invoice

POST /invoices

HTTP Response: 201 Created
Location: /invoices/#{new_id}

Sample post:

<invoice>
  <due-at type="date">2008-02-06</due-at>
  <!-- human representation for due at -->
  <due-at-human-format>due upon receipt</due-at-human-format>
  <client-id type="integer">8</client-id>
  <!-- see list bellow for accepted values -->
  <currency>United States Dollars - USD</currency>
  <issued-at type="date">2008-02-06</issued-at>
  <notes>Some notes go here</notes>
  <number>82208</number>
  <!-- allowed values:
    free_form:  creates a free form invoice (non-generated).
                Content is added via CSV.
    project:    gathers content from Harvest grouping by projects
    task:       gathers content from Harvest grouping by task
    people:     gathers content from Harvest grouping by people
    detailed:   includes detailed notes -->
  <kind>project</kind>
  <!-- comma separated project ids to gather data from, useless on
  free_form invoices -->
  <projects-to-invoice>3</projects-to-invoice>
  <!-- import hours useless on free_form invoices -->
  <import-hours>yes</import-hours>
  <!-- import expenses useless on free_form invoices -->
  <import-expenses>yes</import-expenses>
  <!-- invoiced period, present for generated invoices -->
  <period-end type="date">2008-03-31</period-end>
  <period-start type="date">2007-06-26</period-start>
  <!-- invoiced period for expenses, present for generated invoices -->
  <expense-period-end type="date">2008-03-31</expense-period-end>
  <expense-period-start type="date">2007-06-26</expense-period-start>
  <updated-at type="datetime">2008-04-09T12:07:56Z</updated-at>
  <created-at type="datetime">2008-04-09T12:07:56Z</created-at>
</invoice>

Note: we accept only a limited set of values for the currency attribute.

You can also create a free form invoice with line items by passing in the csv-line-items attribute.

Sample post:

<invoice>
  <due-at type="date">2008-02-06</due-at>
  <due-at-human-format>due upon receipt</due-at-human-format>
  <client-id type="integer">8</client-id>
  <currency>United States Dollars - USD</currency>
  <issued-at type="date">2008-02-06</issued-at>
  <notes>Some notes go here</notes>
  <number>82208</number>
  <kind>free_form</kind>
  <!-- Line items in CSV format -->
  <csv-line-items>
kind,description,quantity,unit_price,amount,taxed,taxed2,project_id
Service,Security support / Apply upgrades,0.68,80.00,54.4,true,false,3
Service,Security support / Intrusion detection,0.57,80.00,45.6,true,false,3
Service,Backend Programming / Forum admin,1.20,80.00,96.0,true,false,3
  </csv-line-items>
</invoice>

Update an existing invoice

PUT /invoices/#{invoice_id}

HTTP Response: 200 OK
Location: /invoices/#{invoice_id}

Sample put:

<invoice>
  <due-at type="date">2008-02-06</due-at>
  <!-- human representation for due at -->
  <due-at-human-format>due upon receipt</due-at-human-format>
  <client-id type="integer">8</client-id>
  <!-- see list bellow for accepted values -->
  <currency>United States Dollars - USD</currency>
  <issued-at type="date">2008-02-06</issued-at>
  <notes>Some notes go here</notes>
  <number>82208</number>
</invoice>

You can also update the line items for the invoice by passing in the csv-line-items attribute.

Sample post:

<invoice>
  <!-- if you don't know the project id, you can just leave it of from
  data rows ending the row with a comma. CSV header must allways be
  intact though, or updates will be discarded. -->
  <csv-line-items>
kind,description,quantity,unit_price,amount,project_id
Service,Branding for marketing pages,20,100.00,2000,3
Service,What's in a name,8,100.00,800,3
  </csv-line-items>
</invoice>

Not all attributes need to be passed in, Harvest supports selective updates.


Delete existing invoice

DELETE /invoices/#{invoice_id}

HTTP Response: 200 OK.

Write an existing invoice off

PUT /invoices/#{invoice_id}/mark_as_closed

HTTP Response: 200 OK.