Overview
The Harvest V2 API is a REST API that allows you to interact with your Harvest account programmatically. You can track time, log expenses, create projects, and more.
API requests
Harvest requires applications to authenticate all requests with OAuth2 or Personal Access Tokens. The following HTTP methods are supported:
- GET
- POST
- PATCH
- DELETE
When issuing a GET request, parameters should be included in the URL query string:
curl https://api.harvestapp.com/v2/tasks?page=2&per_page=10 \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])"
When issuing a POST or PATCH request, parameters should be included in the request body. Request parameters can either be formatted in JSON or submitted as form data. When submitting request parameters as JSON, you must pass application/json
in the Content-Type
header.
We also require that each request include a User-Agent
header with both:
- The name of your application
- A link to your application or email address
We use this information to get in touch if you’re doing something wrong (so we can warn you before you’re blocked) or something awesome (so we can congratulate you). Here are examples of acceptable User-Agent
headers:
User-Agent: Trello (http://trello.com/contact)
User-Agent: John's Harvest Integration ([email protected])
Notes about user agents
- If you don’t include a
User-Agent
header, you’ll get a400 Bad Request
response. - If you use a non-standard User Agent or deviate from the pattern suggested above, you may encounter connectivity issues with Harvest’s API.
JSON
curl -X POST https://api.harvestapp.com/v2/tasks \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])" \
-H "Content-Type: application/json" \
-d "{\"name\":\"My New Task\"}"
Form data
curl -X POST https://api.harvestapp.com/v2/tasks \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])" \
-d name="My New Task"
API responses
Harvest formats response bodies in JSON and uses HTTP response codes to indicate the success or failure of an API request. The following are the HTTP status codes that you may encounter when using the API along with a brief explanation of when they occur.
Code | Explanation |
---|---|
200 | Your request was successful. |
201 | A new object has been created. Its representation will be returned in the response body. |
403 | The object you requested was found but you don’t have authorization to perform your request. |
404 | The object you requested can’t be found. |
422 | There were errors processing your request. Check the response body for additional information. |
429 | Your request has been throttled. Refer to the Rate Limiting section for details. |
500 | There was a server error. Contact [email protected] for help. |
Rate limiting
We have an API throttle that blocks accounts that exceed our API rate limits. We reserve the right to tune the limitations, but they are always set high enough to allow a well-behaving interactive program to do its job.
- The rate limit for general API requests is 100 requests per 15 seconds.
- The rate limit for Reports API requests is 100 requests per 15 minutes.
For batch processes and API developers who still need to perfect their code, this throttle may be an inadvertent blocker. Just wait a bit, and try again. Since the throttle is reset with each call, the throttle will lift itself in a few minutes and API calls may resume.
When the rate limit is exceeded Harvest will send an HTTP 429 status code. The number of seconds until the throttle is lifted is sent via the Retry-After HTTP header, as specified in RFC 2616.
Please remember to write your application carefully, caching when possible. In case of abuse you may be blocked, disallowing further API access.
Conventions
When you encounter a value surrounded by curly braces, you should replace it with a value appropriate to your context.
For example, if your Harvest project’s ID is 1234
and the documentation provides the following URL:
https://api.harvestapp.com/v2/projects/{PROJECT_ID}
you would replace the {PROJECT_ID}
with the actual project ID, like so:
https://api.harvestapp.com/v2/projects/1234
We also make use of shell variables in our example requests (e.g. $ACCESS_TOKEN
). If your operating system supports shell variables, you can set shell variables like this:
ACCESS_TOKEN="my-access-token"
ACCOUNT_ID="my-account-id"
USER_AGENT="MyApp ([email protected])"
Then, you can reference them by prefixing them with a $
:
curl -X POST https://api.harvestapp.com/v2/company \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: $USER_AGENT"
This should allow you to copy/paste most of the example requests without needing to change anything aside from IDs.
Data types
Type | Example | Description |
---|---|---|
boolean | true |
Either true or false . |
string | "foo" |
A double-quoted sequence of characters. |
integer | 42 |
A non-negative integer value. |
decimal | 6.8 |
A decimal value. The supported precision is field-dependent. |
date | "2017-12-31" |
An ISO 8601 formatted string containing just the date portion. |
datetime | "2017-12-31T14:59:22Z" |
An ISO 8601 formatted string containing a UTC date and time. |
time | "14:59" "2:59pm" |
A string containing a 12-hour or 24-hour time depending on the Time Format configured for your account. You can check this on the Settings page in your Harvest account or the clock attribute the Company API. |
array | [ 1, 2, 3 ] |
A JSON array. |
object | { name: "value" } |
A JSON object. |