Greenhouse
Greenhouse is one of the largest applicant tracking systems (ATS) and recruiting platforms. The Willow connector targets the Harvest v3 API so an MCP host can query and modify candidates, applications, jobs, interviews, scorecards, and offers without screen-scraping the Greenhouse UI.
The connector is v3-only. Greenhouse has announced that the legacy Harvest v1/v2 API will be removed on August 31, 2026, so this connector deliberately does not surface any v1/v2 endpoints.
Authentication Types
Greenhouse Harvest v3 supports two OAuth 2.0 flows; this connector ships the one most customers can self-serve:
- OAuth 2.0 Client Credentials — Server-to-server flow using a Client ID and Client Secret minted directly in Greenhouse. The auto-generated Integration Service User (ISU) acts as the authorizing user. No end-user consent flow is involved.
- Pros: One credential covers the whole account; rotatable from Greenhouse Dev Center; no end-user prompts; works for back-office automation and data sync.
- Cons: Only users with the Can manage ALL organization's API Credentials developer permission can mint credentials; scopes are configured on the credential itself (you cannot request narrower scopes per token).
- Best for: Custom integrations and internal tooling — what Greenhouse explicitly recommends for non-partner customers.
Note for Greenhouse partners: Partner integrations must use the OAuth 2.0 Authorization Code Grant flow with a Client ID and Secret issued by Greenhouse Partner Support. That flow is not exposed through this built-in connector — partners should contact Willow support to wire it up.
Configuration
You'll need three things to set up the integration in Willow:
- A Client ID and Client Secret generated from Greenhouse Dev Center.
- The token URL:
https://auth.greenhouse.io/token. - The right scopes ticked on the credential in Greenhouse (scopes live on the credential, not in the token request).
Setting up Client Credentials
1. Generate Harvest v3 OAuth credentials in Greenhouse
- Sign in to Greenhouse as a user who has the Can manage ALL organization's API Credentials developer permission. If you don't, ask a site admin to grant it under Configure → Users → Edit user permissions.
- Go to Configure → Dev Center → API Credential Management.
- Click Create new API credential.
- Choose Harvest V3 (OAuth) as the API Type.
- Save the credential. Greenhouse displays the Client ID and Client Secret — copy them now, the secret will not be shown again.
- Click Manage Permissions on the new credential and tick the scopes you need. Each Harvest v3 endpoint enforces a specific scope (for example
harvest:candidates:list,harvest:applications:list,harvest:jobs:read,harvest:notes:create). Grant only what your integration actually uses.
Credentials are issued at the Account level and grant access to all data within their permission scope. Never commit them to source control, and rotate them from Greenhouse Dev Center if you suspect they've leaked. When you rotate the secret, the old secret remains valid for up to one week.
2. (Optional) Pick the authorizing user
When you create an OAuth credential, Greenhouse automatically attaches an Integration Service User (ISU) that becomes the authorizing user for every API call. Every Harvest v3 list endpoint requires the authorizing user to be a Site Admin — the auto-generated ISU is, by default, but if you've reassigned it, point it back at a Site Admin in Greenhouse before connecting.
3. Configure in Willow
- In Willow, go to Integrations → New → Built-in.
- Select Greenhouse and click Use.
- Under Authentication Type, choose Client Credentials.
- Fill in:
- Client ID — from step 1
- Client Secret — from step 1
- Token URL —
https://auth.greenhouse.io/token - Scope — leave blank. Harvest v3 reads scopes from the credential record itself, not the token request, and sending a
scopeparameter has no effect. - Send as JSON — leave off. Greenhouse expects a form-encoded token request body with HTTP Basic authorization for the client credentials.
- Click Save Changes, then Test Connection. Willow will Base64-encode
client_id:client_secret, sendPOST https://auth.greenhouse.io/tokenwithgrant_type=client_credentials, and receive a short-lived bearer token (expires_atis returned as an ISO 8601 timestamp).
4. Verify the integration
Run the List Departments tool with no arguments. A successful 200 response confirms the credentials, scopes, and authorizing user are all wired correctly. If you get a 403 instead, the authorizing user is probably not a Site Admin — fix that in Greenhouse, no need to recreate the credential.
Available Tools
The Greenhouse connector ships 22 tools across the recruiting lifecycle:
Candidates (4 tools)
- List Candidates — paginated candidate/prospect search with email/tag/date filters.
- Create Candidate — create a candidate (or Prospect via the nested
applicationobject). - Update Candidate — patch profile fields. Recruiter and Coordinator are managed on the application object, not here.
- Delete Candidate — irreversible delete. Use Anonymize for GDPR-style erasure that preserves recruiting history (not yet exposed in this connector).
Applications (5 tools)
- List Applications — filter by candidate, job, stage, source, status, prospect flag, and date.
- Move Application — advance to the next stage, move to a specific stage, or transfer to another job.
- Hire Application — mark hired and optionally fill an opening with a start date.
- Reject Application — reject with a reason; optional rejection email and custom fields.
- Unreject Application — reverse a rejection.
Jobs & Job Posts (4 tools)
- List Jobs — filter by status, requisition ID, department, office, confidentiality, and date.
- Create Job — clone a template job to create a new requisition.
- Update Job — patch name, notes, hiring narrative, department/office assignment, and custom fields.
- List Job Posts — career-site listings, with
live,internal, andfeaturedtoggles.
Interviews & Scorecards (3 tools)
- List Interviews — scheduled interviews with status and time-window filters.
- List Scorecards — interview scorecards filterable by application, interviewer, submitter, status.
- List Interviewers — per-interview interviewer assignments and RSVP statuses.
Offers (1 tool)
- List Offers — filter by application, candidate, job, opening, status, and date.
current_only: truereplaces the legacy v1current_offerendpoint.
Organization (5 tools)
- List Users — Greenhouse users (recruiters, hiring managers, interviewers).
- List Offices, List Departments — org structure for filtering jobs/users.
- List Sources — candidate source dictionary.
- List User Roles — role catalog for permission lookups.
Notes (1 tool)
- Create Note — record a note, activity entry, or logged email on a candidate or application.
Pagination
Every list endpoint uses cursor-based pagination. The first response includes a Link response header with a next URL; pass that URL's cursor parameter back into the next call.
Important: when
cursoris set, all other filters are ignored. Pick your filters on the first call only, then walk the cursor without changing them.
Common Use Cases
Incremental application sync into a data warehouse
List Applications with updated_at = "gte|<last sync timestamp>" →
Walk cursor through every page →
For each application, optionally pull related Scorecards, Interviews, and Offers →
Persist into your warehouse keyed by application.id
Auto-advance candidates after a passing scorecard
List Scorecards with status = "complete" and submitted_at = "gte|<last run>" →
For each scorecard, fetch List Applications by candidate_id →
If average rating >= threshold, call Move Application
Reject from a shortlist
List Applications with stage_name = "Final Round" →
For each application not in your shortlist, call Reject Application with
rejection_reason_id and an optional rejection_email
Org-aware candidate routing
List Departments → cache id → name →
List Users with department_ids = <hiring manager's department> →
Use the result to set linked_user_ids on Create Candidate
Troubleshooting
401 Unauthorized from https://auth.greenhouse.io/token
Cause: The Client ID or Client Secret is wrong, has trailing whitespace, or has been rotated/deleted in Greenhouse Dev Center.
Solution:
- Re-copy the Client ID and Secret from Configure → Dev Center → API Credential Management.
- Make sure no whitespace was added when pasting.
- If the secret has been rotated, update Willow with the new secret (you have one week before the old secret stops working).
403 Forbidden on every list endpoint
Cause: The authorizing user is not a Site Admin. Harvest v3 requires Site Admin permissions on every list endpoint.
Solution:
- In Greenhouse, find the Integration Service User (ISU) attached to the credential under API Credential Management.
- Promote that user to Site Admin, or attach the credential to a different user who is one.
- Retry the failing tool — no need to regenerate the credential.
403 Forbidden on a specific endpoint while others work
Cause: The credential is missing the scope that endpoint requires (e.g. trying to call Reject Application with a credential that has only harvest:applications:list).
Solution:
- Open Manage Permissions on the credential in Greenhouse.
- Tick the missing scope (e.g.
harvest:applications:reject) and save. - Retry. New tokens minted by Willow will include the new scope automatically.
422 Unprocessable Content on a write tool
Cause: A required field is missing, an enum value is wrong, or a foreign key (rejection_reason_id, to_stage_id, template_job_id, etc.) doesn't exist or is closed.
Solution:
- Check the response body — Greenhouse returns a
{ "message": "Validation error", "errors": [{ "field": "...", "message": "..." }] }payload that pinpoints the bad field. - Use the relevant List ... tool to discover valid IDs (e.g. List Departments before setting
department_id, List Users before settingemail_from_user_id).
429 Too Many Requests
Cause: Harvest is rate-limited per credential per 10 seconds. The exact ceiling is set by Greenhouse and shown in the X-RateLimit-Limit response header.
Solution:
- Back off using the
Retry-Afterheader value (in seconds). - Prefer larger
per_page(up to 500) over many small calls. - For long-running syncs, filter on
updated_at = "gte|<last sync>"so you only fetch what changed.
Trying to call v1/v2 paths and getting deprecation warnings
Cause: Custom prompts referencing legacy paths like /v1/candidates/{id}/activity_feed or /v1/scheduled_interviews.
Solution: Use the v3 equivalents — the connector exposes only v3 routes. The v1/v2 API is removed on August 31, 2026.