Skip to main content

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:

  1. A Client ID and Client Secret generated from Greenhouse Dev Center.
  2. The token URL: https://auth.greenhouse.io/token.
  3. 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

  1. 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 ConfigureUsersEdit user permissions.
  2. Go to ConfigureDev CenterAPI Credential Management.
  3. Click Create new API credential.
  4. Choose Harvest V3 (OAuth) as the API Type.
  5. Save the credential. Greenhouse displays the Client ID and Client Secret — copy them now, the secret will not be shown again.
  6. 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.
Treat credentials like passwords

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

  1. In Willow, go to IntegrationsNewBuilt-in.
  2. Select Greenhouse and click Use.
  3. Under Authentication Type, choose Client Credentials.
  4. Fill in:
    • Client ID — from step 1
    • Client Secret — from step 1
    • Token URLhttps://auth.greenhouse.io/token
    • Scope — leave blank. Harvest v3 reads scopes from the credential record itself, not the token request, and sending a scope parameter has no effect.
    • Send as JSON — leave off. Greenhouse expects a form-encoded token request body with HTTP Basic authorization for the client credentials.
  5. Click Save Changes, then Test Connection. Willow will Base64-encode client_id:client_secret, send POST https://auth.greenhouse.io/token with grant_type=client_credentials, and receive a short-lived bearer token (expires_at is 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 application object).
  • 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, and featured toggles.

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: true replaces the legacy v1 current_offer endpoint.

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 cursor is 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:

  1. Re-copy the Client ID and Secret from Configure → Dev Center → API Credential Management.
  2. Make sure no whitespace was added when pasting.
  3. 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:

  1. In Greenhouse, find the Integration Service User (ISU) attached to the credential under API Credential Management.
  2. Promote that user to Site Admin, or attach the credential to a different user who is one.
  3. 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:

  1. Open Manage Permissions on the credential in Greenhouse.
  2. Tick the missing scope (e.g. harvest:applications:reject) and save.
  3. 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:

  1. Check the response body — Greenhouse returns a { "message": "Validation error", "errors": [{ "field": "...", "message": "..." }] } payload that pinpoints the bad field.
  2. Use the relevant List ... tool to discover valid IDs (e.g. List Departments before setting department_id, List Users before setting email_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:

  1. Back off using the Retry-After header value (in seconds).
  2. Prefer larger per_page (up to 500) over many small calls.
  3. 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.

Additional Resources