Introduction

The V2 API requires an access token to authenticate requests. There are two options available to you:

  • A Personal Access Token which is tied directly to you and is the quickest way to start playing around with the API.
  • Implementing a full OAuth2 Authentication flow which allows other people to use your Harvest integrations.

Personal Access Tokens

The API can be accessed by creating a Personal Access Token from the Developers section of Harvest ID. After creating it you’ll be provided with a random token and a list of your acccount IDs.

Personal Access Tokens are the preferred method when you want to write your own scripts that consume our API. Typical use cases for Personal Access Tokens are scripts that build custom reports, sync data between different accounts, or automating tasks that would otherwise take a long time when done manually.

They replace the Basic Authentication method that was used in our v1 API, as it’s more secure–on your Developers section you’ll see a list of all your Personal Access Tokens, when they were last used, and you will be able to easily revoke them if necessary.

Once generated, they can be used to access the API by either providing it in the Authorization header or including it in the query string. Each request will require your account ID as well, since you can use this Personal Access Token to access any of your Harvest or Forecast accounts.

Header Authentication Example

curl -H "Authorization: Bearer $ACCESS_TOKEN" \
     -H "Harvest-Account-Id: $ACCOUNT_ID" \
     -H "User-Agent: MyApp (yourname@example.com)" \
     https://api.harvestapp.com/v2/users/me

Query String Authentication Example

curl -H "User-Agent: MyApp (yourname@example.com)" \
     "https://api.harvestapp.com/v2/users/me?access_token=$ACCESS_TOKEN&account_id=$ACCOUNT_ID"

OAuth2 Application

If you are interested in building integrations that other users can use, you will need to register an OAuth2 Application, also known as an OAuth2 Client. The application can be created from the Developers section of Harvest ID, and you will be required to provide some information:

  • Name–name of your application.
  • Redirect URL–the URL in your integration; successful authentications will be redirected to by default.
  • Origin URL–(optional) when provided, Cross-Origin Resource Sharing will be enabled from this origin for tokens generated from your app. See the Client Side Applications section for more information.
  • Multi Account–does your integration supports multiple user account access or works with only one authenticated account.
  • Products–scope of access requested; can be either Harvest, Forecast or both. It is advised to pick the minimal scope required for the integration to work.

OAuth2 Authorization Flow

For Server Side Applications

We use the Authorization Code flow for server-side authorization. To start the authorization flow, you need to redirect the user to the following URL:

https://id.getharvest.com/oauth2/authorize?client_id={CLIENT_ID}&response_type=code

This URL allows the user to authenticate on Harvest ID and let them authorize access to their account(s) depending on your OAuth2 Application settings and their choice.

This endpoint accepts other parameters:

  • state–(optional) used to pass any value that will get sent back to you when redirecting back to your application.
  • redirect_uri–(optional) the default Redirect URL can be further customized here if needed, but needs to start with the Redirect URL registered with your Application.

After a successful authorization, user will be redirected back to the Redirect URL you specified when registering your OAuth2 application, or the redirect_uri you provided. These parameters will be attached:

  • code–an authorization code that you will have to exchange for a set of Refresh and Access Tokens. You will be able to use this Access Token to access the user’s account on his behalf.
  • state–(optional) contains the original value for the state parameter that was passed at the beginning of the authorization.
  • scope–contains a list of space separated strings describing the granted access scope. See the Scopes section for further explanation.

Once you have the Authorization Code, you can exchange it for a set of Access and Refresh Tokens:

curl -X POST \
  -H "User-Agent: MyApp (yourname@example.com)" \
  -d "code=$AUTHORIZATION_CODE" \
  -d "client_id=$CLIENT_ID" \
  -d "client_secret=$CLIENT_SECRET" \
  -d "grant_type=authorization_code" \
  'https://id.getharvest.com/api/v1/oauth2/token'

Response:

{
  "access_token":  "{ACCESS_TOKEN}",
  "refresh_token": "{REFRESH_TOKEN}",
  "token_type":    "bearer",
  "expires_in":    1209600
}

For Client Side Applications

We use the Implicit Grant Flow for client-side authorization. These are typically applications that run entirely on the browser and issue Cross-Origin requests to our API.

The difference is that you’ll get a single Access Token back that you can use immediately. This access token will only work within the Origin URL you specified when registering the appication, and must authorize API requests passing the access token and account ID via query string due to Cross-Origin Resource Sharing restrictions.

If a backend server is available, we recommend the Authorization Code flow, because it’s more secure and the access token is never visible by a browser.

To start the authorization flow, redirect the user to the following URL:

https://id.getharvest.com/oauth2/authorize?client_id={CLIENT_ID}&response_type=token

This URL allows the user to authenticate on Harvest ID and let them authorize access to their account(s) depending on your OAuth2 Application settings and their choice.

This endpoint accepts other parameters:

  • state–(optional) used to pass any value that will get sent back to you when redirecting back to your application.
  • redirect_uri–(optional) the default Redirect URL can be further customized here if needed, but needs to start with the Redirect URL registered with your Application.

After a successful authorization, user will be redirected back to the Redirect URL you specified when registering your OAuth2 application, or the redirect_uri you provided. These parameters will be attached:

  • access_token–the Access Token token that can be used to authenticate the requests on the user’s behalf.
  • token_type–will always be bearer.
  • expire_in–time in seconds until the token expires.
  • state–(optional) contains the original value for the state parameter that was passed at the beginning of the authorization.
  • scope–contains a list of space separated strings describing the granted access scope. See the Scopes section for further explanation.

Scopes and account access

Personal Access Tokens have the all scope by default, so you have full access to all of your accounts. For OAuth2 Applications, it can vary depending on the options you selected and the authorization the user might give you.

The scope can contain one or more of these values:

  • harvest:{ACCOUNT_ID}–a Harvest account ID that the user granted access to.
  • forecast:{ACCOUNT_ID}–a Forecast account ID that the user granted access to.
  • harvest:all–the user granted access to all of his Harvest accounts.
  • forecast:all–the user granted access to all of his Forecast accounts.
  • all–the user granted access to all of his accounts.

If you registered your app as needing access to just one account, the user will choose which account to authorize, and you’ll only get one scope back, either harvest:{ACCOUNT_ID} or forecast:{ACCOUNT_ID}, depending on which products you chose to work with.

If your app can work with multiple accounts, you can get any combination of those scopes depending on what the user chose to authorize. Use that list or consume Harvest ID’s accounts endpoint to figure out which accounts you can access:

GET https://id.getharvest.com/api/v1/accounts

Example Request (note that the account ID is not necessary):

curl "https://id.getharvest.com/api/v1/accounts" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "User-Agent: MyApp (yourname@example.com)"

Example Response:

{
  "user": {
    "id": 1,
    "first_name": "Albert",
    "last_name": "Llop",
    "email": "albert@example.com"
  },
  "accounts": [
    {
      "id": 10254,
      "name": "Sterling Cooper Advertising Agency",
      "product": "harvest"
    },
    {
      "id": 88888,
      "name": "Iridesco",
      "product": "forecast"
    },
    {
      "id": 88903,
      "name": "Sterling Cooper Advertising Agency",
      "product": "forecast"
    }
  ]
}