Getting Started with Greenhouse API
With Greenhouse’s Harvest, you can access most of your Greenhouse data!
The Harvest API was designed to allow customers to export their data from Greenhouse. However, it can also be used to:
- Update candidate information.
- Add attachments to candidate profiles.
- Advance, move, and reject applications.
HTTP Basic Authentication
Before interacting with Greenhouse's API, you must authenticate your requests to ensure they are secure. Greenhouse uses HTTP Basic Auth for authentication. In this setup, your Greenhouse API token is the username, and the password is left blank.
Steps to Authenticate:
1. Obtain API Credentials:
- Navigate to your Greenhouse account
- Go to Configure > Dev Center > API Credential Management
- Create a new API Key of type "Harvest"
- Assign the necessary permissions to the key, specifying which endpoints it can access. To add or remove endpoint permissions on an API key, go to the Dev Center in Greenhouse, click "API Credential Management," then click "Manage Permissions" next to your Harvest API Key. From there, check or uncheck permissions for any endpoints.
2. Setting credentials with cURL:
- Using
curl
, an example request would look like:
curl -u your_api_key: https://harvest.greenhouse.io/v1/candidates
Here, your_api_key is your API key generated in the previous step. The command, -u your_api_key: tells curl to use HTTP Basic Authentication with your API key as the username and an empty password.
3. Authorization Header:Most HTTP clients will automatically use a given username and password to generate the required Authorization header. However, you may need to explicitly set this header. The header has the following format:
Authorization: Basic <base64("username:password")>
Note: Since only a username needs to be provided in our case, you'll need to append a : (colon) to your Greenhouse API token and then Base64 encode the resulting string.
Deep Dive into Greenhouse API Endpoints
The Greenhouse Harvest API provides a range of endpoints that allow developers to access various candidates, applications, and jobs data.
Here are the most commonly used endpoints, along with practical use cases.
1. GET /v1/candidates
- Description: List all of an organization's candidates.
- cURL Request:
curl -X GET 'https://harvest.greenhouse.io/v1/candidates?per_page=100&page=1' \
-H 'Authorization: Basic <base64_encoded_api_key>'
- Parameters:
page
: Specifies the page number of the results to retrieve. Defaults to 1 if not provided.per_page
: Determines the number of records per page. The maximum allowed value is 500. If you provide a value exceeding this limit, you'll receive a422 Unprocessable Entity
error.
- Use Case: Obtain all the candidates in a company from Greenhouse into your system.
2. POST /v1/candidates
- Description: Create a new candidate.
- cURL Request:
curl -X POST 'https://harvest.greenhouse.io/v1/candidates'
-H "Content-Type: application/json"
-H "On-Behalf-Of: {greenhouse user ID}"
-H "Authorization: Basic <base64_encoded_api_key>"
- Parameters:
greenhouse user ID
: ID of the user issuing this request. Required for their auditing purposes.
- JSON Body Parameters: The above command takes a JSON request, wherein
first_name
,last_name
, andapplications
are required fields. For example, a typical JSON will be structured like this:
{
"first_name": "John",
"last_name": "Locke",
"company": "The Tustin Box Company",
"title": "Customer Success Representative",
"is_private": false,
"phone_numbers": [
{
"value": "555-1212",
"type": "mobile"
}
],
"addresses": [
{
"value": "123 Fake St.",
"type": "home"
}
],
"email_addresses": [
{
"value": "john.locke+work@example.com",
"type": "work"
},
{
"value": "john.locke@example.com",
"type": "personal"
}
],
"website_addresses": [
{
"value": "johnlocke.example.com",
"type": "personal"
}
],
"social_media_addresses": [
{
"value": "linkedin.example.com/john.locke"
},
{
"value": "@johnlocke"
}
],
"educations": [
{
"school_id": 459,
"discipline_id": 940,
"degree_id": 1230,
"start_date": "2001-09-15T00:00:00.000Z",
"end_date": "2004-05-15T00:00:00.000Z"
}
],
"employments": [
{
"company_name": "Greenhouse",
"title": "Engineer",
"start_date": "2012-08-15T00:00:00.000Z",
"end_date": "2016-05-15T00:00:00.000Z"
}
],
"tags": [
"Walkabout",
"Orientation"
],
"applications": [
{
"job_id": 215725
},
{
"job_id": 185289
}
]
}
- Use Case: Add a new candidate to an Organization using the Greenhouse system.
3. POST/v1/candidates/{id}/attachments
- Description: Post an attachment to a candidate's profile by the candidate
id
. - cURL Request:
curl -X POST 'https://harvest.greenhouse.io/v1/candidates/{id}/attachments'
-H "Content-Type: application/json"
-H "On-Behalf-Of: {greenhouse user ID}"
-H "Authorization: Basic <base64_encoded_api_key>"
- Parameters:
greenhouse user ID
: ID of the user issuing this request. Required for their auditing purposes.
- JSON Body Parameters: The above command takes a JSON request, wherein
filename
,type
, andcontent_type
are required fields. For example, a typical JSON will be structured like this:
{
"filename" : "resume.pdf",
"type" : "resume",
"content" : "R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs...",
"content_type" : "application/pdf"
}
- Use Case: Add an attachment to a candidate in an Organization using the Greenhouse system.
Pagination and Rate limits
Pagination
The Greenhouse Harvest API paginates responses for endpoints returning collections. Pagination details are provided in the Link
response header, following the RFC-5988 standard. This header includes URLs for next
, prev
, and last
pages. If the Link
header is absent, it indicates that the response contains only a single page of results.
Implementation Steps:
- Initial Request: Make a GET request to the desired endpoint, e.g.,
GET /v1/candidates
. - Inspect the
Link
Header: Check theLink
header in the response for pagination URLs. - Iterate Through Pages: Continue making requests to the
next
URL provided in theLink
header until it is no longer present, indicating the end of the paginated results.
Example:
Suppose the Link
header in the response is:
Link: <https://harvest.greenhouse.io/v1/candidates?page=2&per_page=100>; rel="next",
<https://harvest.greenhouse.io/v1/candidates?page=10&per_page=100>; rel="last"
You would then make a request to the next URL to retrieve the subsequent page of results.
Notes:
Rate Limiting
The Greenhouse Harvest API enforces rate limits to ensure fair usage:
- Limit: The number of allowed requests per 10-second window is specified in the
X-RateLimit-Limit
response header. - Remaining: The
X-RateLimit-Remaining
header indicates how many requests you have left in the current window. - Exceeding the Limit: If you exceed the rate limit, the API responds with an HTTP 429 status code. The response includes:
Retry-After
Header: Specifies the number of seconds to wait before retrying.X-RateLimit-Reset
Header: Indicates the timestamp when the rate limit will reset.
Best Practices:
- Monitor Headers: Always check the
X-RateLimit-Remaining
header to monitor your usage. - Implement Backoff Strategy: If you receive a 429 response, respect the
Retry-After
duration before making new requests.
Troubleshooting Guide
Error Handling
Harvest API can return errors for various reasons, such as invalid requests or server issues. Greenhouse uses standard HTTP status codes to indicate success or failure.
Common Status Codes:
Get Started With with Greenhouse API Using Bindbee
Integrating with Greenhouse shouldn’t feel like a battle.But for most teams, it ends up being a major time sink—draining valuable engineering resources.
Why put your developers through the grind when Bindbee can get you live with Greenhouse in just minutes?
Setting up Greenhouse connector with Bindbee
- Sign up with Bindbee and navigate to the dashboard.
- Create a Connector:
- Click on Create Connector from the dashboard.
- Select HRIS as the type of integration. Enter customer details and give your connector a unique ID (e.g., Employment_Hero_Integration).
- Generate a Magic Link:
- After setting up the connector, click Create Link to generate a magic link. This will allow the customer to authenticate the connection with Greenhouse.
- Open the link and enter the necessary credentials. This step establishes the connection between Greenhouse and Bindbee.
- Sync the Connector:
- Once the connection is made, the connector will begin syncing data from BambooHR. This may take a few minutes depending on the size of the data. You can track the sync status in the connector section.
- Access the Synced Data:
- After syncing, go to the Employee section in the Bindbee dashboard and select Get Employees to retrieve employee data from BambooHR.
- Get the API Key and Connector Token:
- Copy the API key and the x-connector-token from the Bindbee dashboard, which you will need to make authenticated API requests.
Retrieving Employee Data with Bindbee
Once the Greenhouse data has been synced, you can retrieve employee data on to your application via the Bindbee API.
Here’s a step-by-step process for accessing synced data from BambooHR through Bindbee’s unified API:
1. Request Setup:
- Use the Bindbee API to send a request for employee data. You’ll need both your Bindbee API token and the x-connector-token.
2. Example cURL Request:
curl --request GET \
--url https://api.bindbee.com/hris/v1/employees \
--header 'Authorization: Bearer YOUR_BINDBEE_API_KEY' \
--header 'x-connector-token: YOUR_CONNECTOR_TOKEN'
This request will return a list of employee objects, including details like the employee’s first name, last name, job title, department, and contact information.
3. Sample Response:
{
"items": [
{
"id": "018b18ef-c487-703c-afd9-0ca478ccd9d6",
"first_name": "Kunal",
"last_name": "Tyagi",
"job_title": "Chief Technology Officer",
"department": "Engineering",
"work_email": "kunal@bindbee.dev"
}
]
}
Bulk Employee Data Retrieval
For retrieving large datasets, Bindbee simplifies the process by allowing you to fetch bulk employee data from BambooHR.
The pagination feature helps manage large responses by returning results in pages.
- Pagination Parameters:
- Use the
cursor
andpage_size
parameters to navigate through the results. By default, Bindbee returns 50 records per page. - Example of a paginated request:
- Use the
url = "https://api.bindbee.com/hris/v1/employees?cursor=MDE4YjE4ZWYtYzk5Yy03YTg2LTk5NDYtN2I3YzlkNTQzM2U1&page_size=50"
response = requests.get(url, headers=headers)
- Querying for Specific Employee Data:
- You can further refine your request by filtering based on specific fields, such as manager_id, remote_id, or company_id to get employees under a particular manager or company.
Say hello to Bindbee.
Book a demo with our experts today.