# Greenhouse

![GREENHOUSE_WORDMARK_GREEN.png](https://assets.relyanceuat.xyz/images/docs/34603477931021/34603448305549.png)
Greenhouse is an applicant tracking and hiring tool. They are a talent acquisition software company that offers its suite of tools and services to help businesses with the hiring process and features automated workflows, recruitment analytics, CRM, and onboarding.

> **Action required by August 31, 2026.** Greenhouse is retiring Harvest API v1 and v2
> on that date. Relyance connections that authenticate with the legacy **Custom** method
> (Harvest API Key + Ingestion API Key) stop working when Greenhouse turns v1 off. Set up
> new connections with **Harvest v3 (OAuth)**, and move existing connections over before
> the cutoff — see [Migrate an existing connection](#migrate-an-existing-connection).

Relyance connects to Greenhouse through the **Harvest API v3**. To integrate it you need
a **Harvest v3 (OAuth)** API credential from Greenhouse — a **Client ID** and a
**Client Secret** — with the scopes listed below.

### Permissions Relyance needs

**To create the credential** you must be a Greenhouse **Site Admin**, or a user whose
permissions include **Can manage ALL organization's API credentials**.

**Scopes.** A Harvest v3 credential only reaches the endpoints whose scopes are ticked
under **Manage permissions**. Relyance needs the *list* scope for each resource it
classifies. Tick every scope in this table; a missing one does not fail the connection
test, it fails the scan when it reaches that endpoint.

| Scope | What Relyance reads with it |
| --- | --- |
| `harvest:candidates:list` | Candidate profiles |
| `harvest:applications:list` | Job applications |
| `harvest:attachments:list` | Resumes and other documents attached to candidates and applications |
| `harvest:candidate_educations:list` | Candidate education history |
| `harvest:candidate_employments:list` | Candidate employment history |
| `harvest:notes:list` | Candidate notes, emails and activity entries (the v1 activity feed) |
| `harvest:offers:list` | Offers extended to candidates |
| `harvest:jobs:list` | Job listings |
| `harvest:job_hiring_managers:list` | Hiring managers assigned to jobs |
| `harvest:job_owners:list` | Job owners — recruiters, coordinators and sourcers |
| `harvest:job_interview_stages:list` | Interview stages on each job |
| `harvest:default_interviewers:list` | Default interviewers configured on interview stages |
| `harvest:interviews:list` | Scheduled interviews |
| `harvest:interviewers:list` | Interviewers assigned to scheduled interviews |
| `harvest:scorecards:list` | Interview scorecards |
| `harvest:scorecard_question_answers:list` | Interviewers' written scorecard answers |
| `harvest:users:list` | Greenhouse user accounts |
| `harvest:demographic_questions:list` | Demographic survey questions |
| `harvest:demographic_answers:list` | Demographic survey answers |

**DSR only:** add `harvest:candidates:destroy` (**Delete candidate**) if you enable
**Data Subject Requests** on the connection. Erasure requests permanently delete the
candidate and all of their applications, attachments, scorecards, notes and other
associated records — Greenhouse cannot undo this. Leave the scope off for a
discovery-only connection and the integration cannot delete anything.

**Which user the credential acts as.** When Greenhouse creates a Harvest v3 credential
it also creates an **integration service user** that owns the credential, and Relyance
acts as that user by default. Nothing else is needed. If your organization requires API
activity to be attributed to a named person instead, you can enter that person's numeric
Greenhouse **User ID** in Relyance; that user must be a **Site Admin**, and if the
account is later deactivated the connection starts failing even though the Client ID
and Secret are still valid.

### In Greenhouse

1. Sign in to Greenhouse as a Site Admin (or a user who can manage all API credentials).
2. Click the **Configure** icon (the gear) in the navigation bar, then **Dev Center** in
   the left menu.
3. Click **API Credential Management**.
4. Click **Create new API credentials**.
5. Fill in the form:
    - **API type**: **Harvest v3 (OAuth)**. Do not pick **Harvest** — that is the v1 key
      Greenhouse is retiring.
    - **Partner**: **Custom** (or **unlisted vendor**) — Relyance is not a listed Harvest
      v3 partner.
    - **Description**: something you will recognise later, e.g. `Relyance AI`.
6. Click **Manage permissions** and tick every scope in the table above. Add
   **Delete candidate** (`harvest:candidates:destroy`) only if you will enable DSRs.
   Click **Save**.
7. Copy the **Client ID** and the **Client Secret** and store them somewhere safe. The
   **Client Secret is shown only once**; if you lose it you have to create a new
   credential. The Client ID stays visible in the credential list.
8. Click **I have stored the client credentials**.

Optional — only if you need requests attributed to a named user: open **Configure** →
**Users**, click the user, and copy the number at the end of the browser URL. That is
the **User ID** for the Relyance form.

### In the Relyance AI application

1. Login to your Relyance AI account.
2. Navigate to the **Settings** (bottom-left corner).
3. Select **Integrations**.
4. Search and locate the **Greenhouse** integration card and click on it.
5. Click on the **Add Connection** button on the top right.
6. Provide a meaningful name for the integration and click on the **Add** button.
7. In the **Overview** section, select the integration features you wish to enable for the integration, review the **Scope and Permission**, and **Endpoint** details and click on **Continue**. For more details, see [Integration Features](/docs/introduction-to-relyance-ai/integration-features/). If you enable **Data Subject Requests**, the Greenhouse credential must carry the **Delete candidate** scope described above.
8. In the **Connection** section, provide the appropriate values and click on **Continue**,
    - **Connection Name**: This property allows you to update the integration specified in Step 6. If you have multiple integrations for the same vendor, you may want to assign distinct names to each. This helps streamline filtering by **Discovery Source** across the **Inventory**, **Visual** **Maps**, **Assets**, and **Data Flow Analysis** pages.
    - **Rescan Frequency**: This property allows you to configure how often Relyance executes scans against this Vendor connection.
    - **Business Atlas Associations** (required): the business entities or products that newly discovered third parties, services and assets from this integration are attributed to. Choose at least one from the **Select Associations** dropdown — the wizard will not advance past this step without one. For more details, see [Business Atlas](/docs/other-settings/business-atlas-overview/).
9. In the **Authentication** section, choose **Harvest v3 (OAuth)** as the authentication method, then:
    - **Harvest v3 Client ID**: the Client ID from Greenhouse.
    - **Harvest v3 Client Secret**: the Client Secret from Greenhouse.
    - **Harvest v3 User ID** (optional): leave blank to act as the credential's integration service user. Fill it only if you need activity attributed to a specific Site Admin.
    - Click on **Continue**. Relyance exchanges the Client ID and Secret for a token and reads one page of candidates to verify the credential. If a scope is missing, the error names it (for example `harvest:candidates:list`) — add it under **Manage permissions** in Greenhouse and try again.
10. This step applies only if the **Data Inspection** check box was enabled in Step 7. In the Data Inspection section, provide the appropriate values and click on **Continue**,
    - **Minimum Confidence Level:** This property adjusts the sensitivity of the Data Inspection feature. Lower likelihoods (e.g., unlikely) offer more coverage but may produce false positives, while higher sensitivity (e.g., very likely) provides greater accuracy but less coverage.
11. Review the configuration summary from the **Completion** section and click on **Finish.**
12. Confirm the integration Status reflects **Connected.**

![Screenshot](https://assets.relyanceuat.xyz/images/docs/34603477931021/41498548380301.png)

![Screenshot](https://assets.relyanceuat.xyz/images/docs/34603477931021/41498556665997.png)

![Screenshot](https://assets.relyanceuat.xyz/images/docs/34603477931021/41498556674189.png)

![Screenshot](https://assets.relyanceuat.xyz/images/docs/34603477931021/41498548396941.png)

![Screenshot](https://assets.relyanceuat.xyz/images/docs/34603477931021/41498548400525.png)

![Screenshot](https://assets.relyanceuat.xyz/images/docs/34603477931021/41498548404877.png)

### Migrate an existing connection

If your Greenhouse connection was set up with the **Custom** method (Harvest API Key,
Ingestion API Key and On Behalf of Email), it uses Harvest v1 and stops working when
Greenhouse retires v1 on **August 31, 2026**. Move it over before then:

1. In Greenhouse, create a **Harvest v3 (OAuth)** credential with the scopes above
   (the [In Greenhouse](#in-greenhouse) steps). Keep the old Harvest and Ingestion keys
   active for now.
2. In Relyance, add a **new** Greenhouse connection with the **Harvest v3 (OAuth)**
   method (the [In the Relyance AI application](#in-the-relyance-ai-application)
   steps). Give it the same features (Data Inspection, DSR) and Business Atlas
   associations as the connection it replaces. Both connections can run side by side
   while you switch.
3. Wait for the new connection to show **Connected** and for its first scan to finish.
4. Delete the old **Custom** connection in Relyance, then revoke the old **Harvest** and
   **Candidate Ingestion** API keys in Greenhouse under **API Credential Management**.

Discovery sources, inventory entries and data-flow attribution follow the connection
name, so give the new connection a name that makes the change obvious to anyone
filtering by **Discovery Source** later.

What changes on v3, for anyone who audits the connection:

- **Authentication** is OAuth 2.0 client credentials (a short-lived token minted from
  your Client ID and Secret) instead of a static API key sent with every request.
- **No Ingestion API key and no On Behalf of Email.** Requests are attributed to the
  credential's integration service user (or the optional User ID), so the extra key and
  the live-user requirement go away.
- **Per-resource scopes** replace the v1 endpoint checklist. Records that v1 embedded
  inside a candidate — education, employment, attachments, notes — are separate v3
  resources, which is why the scope list is longer than the v1 permission list was.
- **Data Subject Requests** run against the same v3 credential; only the
  **Delete candidate** scope is needed on top of the list scopes.

### Legacy: Custom (Harvest API v1) — retiring August 31, 2026

These steps are kept for organizations that still have a **Custom** connection. Do not
set up a new connection this way; Greenhouse will not serve v1 after the cutoff and the
connection will fail. Follow [Migrate an existing connection](#migrate-an-existing-connection) instead.

The legacy method needs **two** keys and a user email, and they do different jobs:

- **Harvest API Key** — reads candidates, applications, interviews and the
  demographic-question data. Its permission list must include the endpoints
  Relyance calls: list candidates, list applications, list interviews, and the
  demographics questions and answers.
- **Ingestion API Key** — used for the ingestion API; a Harvest key alone is not
  enough.
- **On Behalf of Email** — Greenhouse attributes API activity to a user, so this
  must be a live account. If that person is deactivated, calls start failing even
  though both keys are still valid. For DSR delete operations this account needs
  **Site Admin** permission in Greenhouse.

**Generate the Harvest API Key:** click the **Configure** gear → **Dev Center** →
**API Credential Management** → **Create New API Key**; select **Harvest** as the API
type; copy the key; click **Manage Permissions** and enable the endpoints above.

**Generate the Ingestion API Key:** back in **API Credential Management**, click
**Create New API Key**; select **Candidate Ingestion** as the API type; select
**Relyance Inc.** under **Partners**; copy the key.

In the Relyance connection wizard, choose **Custom** as the authentication method and
provide the **Harvest API Key**, **Ingestion API Key**, **On Behalf of Email** and
**Maximum concurrent API calls**.

![Screenshot](https://assets.relyanceuat.xyz/images/docs/34603477931021/41498548355597.png)

![Screenshot](https://assets.relyanceuat.xyz/images/docs/34603477931021/41498548364173.png)

![Screenshot](https://assets.relyanceuat.xyz/images/docs/34603477931021/41498556654349.png)

![Screenshot](https://assets.relyanceuat.xyz/images/docs/34603477931021/41498556650381.png)

### Troubleshooting

- **"Unable to authenticate to Greenhouse Harvest v3 - verify your credentials"** —
  Greenhouse rejected the Client ID / Client Secret pair. Check for a copy-paste
  truncation; if the secret was lost, create a new credential (the secret is shown
  once).
- **"Greenhouse Harvest v3 credential is missing required scopes: … (harvest:…:list)"**
  — the credential authenticates but a scope is not ticked. The message names the
  scope. In Greenhouse open the credential → **Edit** → **Manage permissions**, tick it,
  **Save**, then retry the connection. Added scopes take effect the next time Relyance
  requests a token — a connection re-test does that immediately, and a running scan picks
  it up within the hour when its token expires. No re-authorization is needed on the
  Relyance side.
- **Connected, but a scan finishes with nothing for one resource** — the same cause:
  a list scope missing for that resource (Greenhouse answers 403 for it while the rest of
  the scan proceeds). Compare the credential's ticked scopes with the table above.
- **Connection worked, then started failing** — if you filled in **Harvest v3 User ID**,
  confirm that user is still active and still a Site Admin. If not, clear the field so the
  credential acts as its integration service user.
- **Rate limits** — Harvest v3 limits requests per 30-second window and token requests
  per 60-second window. Relyance paces its calls and backs off on `429` responses, so
  slow scans against a large Greenhouse tenant are expected and not an error.

<!-- terraform-examples:begin (generated from the integration catalog; do not hand-edit) -->

## Manage this integration with Terraform

Connections for this integration can be managed as code with the [Relyance Terraform provider](https://registry.terraform.io/providers/Relyance/relyance/latest). Non-secret fields go in `auth.params`; secret fields go in `auth.secrets_wo`, which is write-only — never stored in Terraform state. Rotate secrets by bumping `auth.secrets_wo_version`.

### API key

```hcl
resource "relyance_integration_connection" "greenhouse_0" {
  vendor = "greenhouse"
  name   = "<your connection name>"

  auth = {
    method = "api-key"
    params = {
      ON_BEHALF_OF = "<ON_BEHALF_OF>"
      data_storage_location = "us"
    }
    # Secret fields are write-only: sent to Relyance, never stored in state.
    secrets_wo = {
      HARVEST_API_KEY = var.greenhouse_harvest_api_key
      INGESTION_API_KEY = var.greenhouse_ingestion_api_key
    }
    secrets_wo_version = 1
  }

  scans = { "data-inspection" = { enabled = true } }
}
```

### Client ID & secret

```hcl
resource "relyance_integration_connection" "greenhouse_1" {
  vendor = "greenhouse"
  name   = "<your connection name>"

  auth = {
    method = "client-credentials"
    params = {
      HARVEST_V3_CLIENT_ID = "<HARVEST_V3_CLIENT_ID>"
      data_storage_location = "us"
    }
    # Secret fields are write-only: sent to Relyance, never stored in state.
    secrets_wo = {
      HARVEST_V3_CLIENT_SECRET = var.greenhouse_harvest_v3_client_secret
    }
    secrets_wo_version = 1
  }

  scans = { "data-inspection" = { enabled = true } }
}
```

<!-- terraform-examples:end -->
