Earlier API versions documentation: v1 v2


Release notes

3.0

Our goal with version 3 is to provide a more familiar REST interface while moving pieces in the backend to enable us to add new organization level features to the API.


The Hustle Public API exposes a RESTful interface to provide programmatic access to resources within your Hustle account. The API is defined using the OpenAPI specification (aka Swagger) which can be downloaded above and used to generate a client in various languages. This may help speed up integration with the API, but is not required.

Authentication

Your server-side script or backend application must authenticate to create an access token. Access tokens are used to authorize requests that read and write Hustle resources. To authenticate use your Hustle provided client_id and client_secret to make a request following the OAuth2 client credentials flow. For example, using curl:

Authentication Request and Response
    curl -s -XPOST 'https://api.hustle.com/v2/oauth/token' \
      -H'Content-Type: application/json' \
      -d @- << EOF | jq
    {
      "grant_type": "client_credentials",
      "client_id": "[email protected]",
      "client_secret": "thisisnotarealclientsecret"
    }
    EOF

    {
      "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOi...(truncated)",
      "scope": "read:account write:account",
      "expires_in": 7200,
      "token_type": "Bearer"
    }

Once authenticated, the access_token can be used in the authorization header as a bearer token for requests to Hustle resources:

Authorization Header
Authorization: Bearer <access-token>
where <access-token> is from the create access token response.

Access tokens are JSON Web Tokens (JWT) and are valid for two hours (7200 seconds). It is unlikely a script would have to handle an expired token assuming the script creates a new access token each time it runs. However, long running processes such as a backend application will need to create a new access token upon receiving an unauthenticated error (http status code 401). In this case the request should be retried with the new access token.

API Responses

Every response from the api, including errors, will be returned as JSON in the body of the response and the content-type header set accordingly to application/json. Successful responses returning a single resource will contain the following fields at a minimum:

    {
      "id": String,
      "type": String,
      "createdAt": String
    }
where id is Hustle's unique indentifier for the resource, type is the resource type and createdAt is an ISO 8601 formatted string.

Responses returning a list of resources will be returned as an array containing single resource objects as described above, in addition to cursor details. For example:

    {
      "items": Array<Object>,
      "cursor": string,
      "hasMore": boolean
    }
where items is an array of resources, cursor is a string that will let you continue with the next resource in the list, and hasMore is a boolean letting you know when you've reached the end of the list. For more information on how this cursor works, review the Pagination section below.

Error responses will always contain the following fields:

    {
      "code": Number,
      "message": Boolean
    }
where code is the error code, usually the http status code, and message will explain what went wrong.

Pagination

The cursor string briefly described above has information that can be used in subsequent requests to receive the next page of results for list responses. To get the next page pass the cursor as a query parameter in the next request. Optionally you can pass a limit as a query parameter to receive more data per page. The current default limit is 100 results and the max limit is 1000 results, but please note these values may change. The following is an example using limit and cursor to page through a result set:

Request Initial Page
    curl -s -XGET 'https://api.hustle.com/v3/organizations?limit=1' \
      -H'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOi...(truncated)' | jq

    {
      "items": [
        {
          "id": "YGkEfkzz5V",
          "type": "Organization",
          "name": "Campaign One",
          "createdAt": "2019-07-12T03:57:41.869Z"
          ...
        }
      ],
      "cursor": "WzEsMV0",
      "hasMore": true
    }
Request Next Page
    curl -s -XGET 'https://api.hustle.com/v2/organizations?limit=1&cursor=WzEsMV0' \
      -H'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOi...(truncated)' | jq

    {
      "items": [
        {
          "id": "raz9baExYJ",
          "type": "Organization",
          "name": "Campaign Two",
          ...
        }
      ],
      "cursor": "WzIsMV0",
      "hasMore": false
    }
The hasMore field can used to determine if paging should continue. If hasMore is false or the cursor is null then there are no more pages to fetch.

Rate Limiting

Access to the API will be limited to 25 requests per second for endpoints returning resources. When this limit is reached the API will return an error and the request will need to be retried.

Creating an access token is an exception in that it only limits the number of failed attempts to create an access token. After 10 failed attempts to create an access token the ip of the request will be blocked for some period of time, but only for the account in question. Additionally 100 failed attempts in a 24-hour period will result in the requester's ip being blocked.

Best Practices

  1. Treat your client_id and client_secret like a username and password. Exposing these credentials to any untrusted entity could result in a data breach.
  2. Treat access tokens like sessions. Even though they are short-lived, exposing them to an untrusted entity can result in a data breach.
  3. The API must only be used by processes running on a secure machine.
  4. Consider throttling the number of parallel requests to avoid rate limiting.
  5. For long-running processes, use an access token until it expires before requesting a new one.
  6. It's ok to create an access token each time a script runs, but remember that too many failed authentication requests can result in the ip being blocked.
  7. When a 401 is returned from any resource request create a new access token and retry the request with the new access token.