Hustle Public API (v2.1)

Download OpenAPI specification:Download

Earlier API version documentation: v1

Release notes

2.0

Version 2 primarily focuses on aligning the data models between the GET, POST, and PUT endpoints of specific models (such as leads). With this change, our goal is to allow you to use the same data classes for the bodies of all similar types of requests.

  • The create lead endpoints have had their names updated to denote that they also update the lead as well. This was always how they behaved, but it should now be clearer to new users.
  • BREAKING: The createTag endpoint at POST /organizations/{organizationId}/tags has had it's 'tag' property renamed to 'name'
  • BREAKING: The getGroup (GET /organizations/{organizationId}/groups) and getGroups (GET /groups/{groupId}) endpoints now return an object instead of a string.

2.1

  • Added a new updateGroupMembership endpoint to mark leads in groups as inactive or active.
  • Updated the getLeadsByGroup endpoint to take a new scope query parameter. The default behavior is as before in that only active leads in groups will be returned, but now you can specify if you want to return only inactive leads or include them with active leads.

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. We recommend reading through the following sections to get familiar with how the API is structured before moving on to the API Reference.

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:

Single Resource
{
  "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 a nested object for pagination details. For example:

List of Resources
{
  "items": Array<Object>,
  "pagination": {
    "cursor": String,
    "hasNextPage": Boolean,
    "total": Number
  }
}
where items is an array of resources and pagination is an object with paging details. For more information on how pagination works, review the Pagination section below.

Error responses will always contain the following fields:

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

Pagination

The pagination object 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/v2/organizations?limit=1' \
  -H'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOi...(truncated)' | jq

{ "items": [ { "id": "YGkEfkzz5V", "type": "Organization", "name": "Campaign One", "createdAt": "2019-07-12T03:57:41.869Z" } ], "pagination": { "cursor": "WzEsMV0", "hasNextPage": true, "total": 2 } }

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", "createdAt": "2019-07-17T17:50:40.502Z" } ], "pagination": { "cursor": "WzEsMl0", "hasNextPage": false, "total": 2 } }

The hasNextPage field can be used to determine if paging should continue. The total is the number of resources in the entire result set.

Pagination Cursor Limit
The cursor parameter will allow you to iteratively fetch up to 100,000 objects. Requests for objects after that amount will receive 422 error responses. If you are attempting to retrieve large data sets from Hustle, please use the data exports tooling instead.

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 also 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. For scripts it's ok to create an access token each time a script runs, but remember 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.


API Reference

createAccessToken

Create an access token. A valid access token is required to make requests to other endpoints.

Request Body schema: application/json
grant_type
required
string
Value: "client_credentials"
client_id
required
string <email>
client_secret
required
string

Responses

200

Returns an access token and some metadata about the token

400

Malformed request

403

Not authorized

default

Server error

post /oauth/token

Production Public API

https://api.hustle.com/v2/oauth/token

Request samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "grant_type": "client_credentials",
  • "client_id": "[email protected]",
  • "client_secret": "string"
}

Response samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "access_token": "string",
  • "scope": "string",
  • "expires_in": 0,
  • "token_type": "Bearer"
}

createAgent

Add an agent to a group.

path Parameters
groupId
required
string
Request Body schema: application/json
name
required
string
fullName
required
string
phoneNumber
required
string
sendInvite
boolean
Default: false
email
string <email>

Responses

201

Successfully created agent

400

Malformed request

401

Invalid access token

404

Group not found

default

Server error

post /groups/{groupId}/agents

Production Public API

https://api.hustle.com/v2/groups/{groupId}/agents

Request samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "name": "string",
  • "fullName": "string",
  • "phoneNumber": "string",
  • "sendInvite": false,
}

Response samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "id": "string",
  • "type": "string",
  • "name": "string",
  • "fullName": "string",
  • "phoneNumber": "string",
  • "organizationId": "string",
  • "groupId": "string",
  • "createdAt": "2023-12-05T17:19:14Z"
}

getAgents

Retrieve all agents in a group.

path Parameters
groupId
required
string
query Parameters
cursor
string
limit
integer

Responses

200

Returns a list of agents in the group.

400

Malformed request

401

Invalid access token

404

Group not found

default

Server error

get /groups/{groupId}/agents

Production Public API

https://api.hustle.com/v2/groups/{groupId}/agents

Response samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "items":
    [
    ],
  • "pagination":
    {
    }
}

getAgent

Retrieve an agent by id.

path Parameters
agentId
required
string

Responses

200

Returns an agent.

400

Malformed request

401

Invalid access token

404

Agent not found

default

Server error

get /agents/{agentId}

Production Public API

https://api.hustle.com/v2/agents/{agentId}

Response samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "id": "string",
  • "type": "string",
  • "name": "string",
  • "fullName": "string",
  • "phoneNumber": "string",
  • "organizationId": "string",
  • "groupId": "string",
  • "createdAt": "2023-12-05T17:19:14Z"
}

updateAgent

Update an agent.

path Parameters
agentId
required
string
Request Body schema: application/json
name
string
fullName
string
sendInvite
boolean
Default: false

Responses

200

Returns an agent.

400

Malformed request

401

Invalid access token

404

Agent not found

default

Server error

put /agents/{agentId}

Production Public API

https://api.hustle.com/v2/agents/{agentId}

Request samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "name": "string",
  • "fullName": "string",
  • "sendInvite": false
}

Response samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "id": "string",
  • "type": "string",
  • "name": "string",
  • "fullName": "string",
  • "phoneNumber": "string",
  • "organizationId": "string",
  • "groupId": "string",
  • "createdAt": "2023-12-05T17:19:14Z"
}

getOrganizations

Retrieve all organizations for the account.

query Parameters
cursor
string
limit
integer

Responses

200

Returns a list of organizations

400

Malformed request

401

Invalid access token

default

Server error

get /organizations

Production Public API

https://api.hustle.com/v2/organizations

Response samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "items":
    [
    ],
  • "pagination":
    {
    }
}

getOrganization

Retrieve an organization by id.

path Parameters
organizationId
required
string

Responses

200

Returns an organization

400

Malformed request

401

Invalid access token

404

Organization not found

default

Server error

get /organizations/{organizationId}

Production Public API

https://api.hustle.com/v2/organizations/{organizationId}

Response samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "id": "string",
  • "type": "string",
  • "name": "string",
  • "createdAt": "2023-12-05T17:19:14Z"
}

createGroup

Create a group

path Parameters
organizationId
required
string
Request Body schema: application/json
name
required
string
countryCode
required
string
Enum: "US" "CA" "PR"
location
required
object

Responses

201

Successfully created Group

400

Malformed request

401

Invalid access token

404

Organization not found

default

Server error

post /organizations/{organizationId}/groups

Production Public API

https://api.hustle.com/v2/organizations/{organizationId}/groups

Request samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "name": "string",
  • "countryCode": "US",
  • "location":
    {
    }
}

Response samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "id": "string",
  • "type": "string",
  • "name": "string",
  • "description": "string",
  • "countryCode": "string",
  • "active": true,
  • "location":
    {
    },
  • "organizationId": "string",
  • "preferredAreaCodes":
    [
    ],
  • "timezone": "string",
  • "createdAt": "2023-12-05T17:19:14Z"
}

getGroups

Retrieve an organization's groups.

path Parameters
organizationId
required
string
query Parameters
cursor
string
limit
integer

Responses

200

Returns a list of groups

400

Malformed request

401

Invalid access token

404

Groups not found

default

Server error

get /organizations/{organizationId}/groups

Production Public API

https://api.hustle.com/v2/organizations/{organizationId}/groups

Response samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "items":
    [
    ],
  • "pagination":
    {
    }
}

getGroup

Retrieve a group by id.

path Parameters
groupId
required
string

Responses

200

Returns an organization

400

Malformed request

401

Invalid access token

404

Group not found

default

Server error

get /groups/{groupId}

Production Public API

https://api.hustle.com/v2/groups/{groupId}

Response samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "id": "string",
  • "type": "string",
  • "name": "string",
  • "description": "string",
  • "countryCode": "string",
  • "active": true,
  • "location":
    {
    },
  • "organizationId": "string",
  • "preferredAreaCodes":
    [
    ],
  • "timezone": "string",
  • "createdAt": "2023-12-05T17:19:14Z"
}

createOrUpdateLeadInGroup

Create a lead and add it to a group or update a lead in a group. This operation is an upsert, and will update the fields of any leads that already exist in the group's parent organization with the associated phone number.

path Parameters
groupId
required
string
Request Body schema: application/json
firstName
required
string
lastName
string
email
string <email>
phoneNumber
required
string

Must be a valid phone number for your Organization's region. Hustle will not accept leads with fake phone numbers e.g. (555) 555-1212

You can check if a number is valid for your region using Google's libphonenumber.

notes