Skip to content

Greenhouse integration · Web hooks + Harvest API v3

Screen Greenhouse applications with HireLayer

Greenhouse already parses resumes when candidates apply. HireLayer adds what it does not do: a score for every application against the job’s criteria, with an explanation per criterion, written back to the candidate as a note your recruiters see in Greenhouse.

Trigger
Web hook: Application created
Greenhouse API
Harvest v3, OAuth client credentials
Write-back
Note, tags, custom fields, employments
Cost
2 to 3 credits per application
Greenhouse + HireLayer
  1. 1A candidate appliesGreenhouseGreenhouse sends the new_candidate_application web hook, with the application, the job and a link to the resume.
  2. 2Parse the resumeHireLayerYour handler downloads the resume and sends it to HireLayer CV Extract.
  3. 3Score against the jobHireLayerHireLayer Match compares the resume with the job’s criteria and returns a score and an explanation per criterion.
  4. 4Write back to GreenhouseGreenhouseA note on the candidate with the score and the gaps, plus a tag such as “Strong match” for filtering.

Use cases

What teams do with HireLayer and Greenhouse

  • Triage high-volume roles

    Every application gets a score and the list of mandatory criteria it meets. Recruiters start with the strongest matches instead of reading in arival order.

  • Explain the shortlist

    The note lists each criterion with its status and the evidence found in the resume, so hiring managers see why a candidate is ahaed.

  • Complete sourced profiles

    For prospects added from a CV, write the parsed work history and education back with the candidate employments and educations endpoints.

  • Normalized skills

    Map free-text skills to the HireLayer taxonomy and store them as tags or a custom field, to search candidates by skill across jobs.

Setup

Connect Greenhouse to HireLayer

This is a small service you run, for example a serverless function or an n8n workflow. A Greenhouse user with developer permissions sets it up; no partner program is needed.

  1. 1

    Create Harvest v3 credentials

    In Greenhouse, open Configure → Dev Center → API Credentials and create Harvest V3 (OAuth) credentials with the scopes your service needs (attachments, notes, tags, jobs). Your service gets a token from https://auth.greenhouse.io/token with the client credentials grant.

  2. 2

    Add a web hook

    In Dev Center → Web Hooks, create a hook for Application created pointing to your service, with a secret key. Greenhouse signs each request with HMAC SHA-256 in the Signature header.

  3. 3

    Extract criteria once per job

    When a job opens, send its description to HireLayer Job Extract and store the criteria. Every applicant to that job is then scored on the same list.

  4. 4

    Parse, score and write back

    For each web hook: verify the signature, download the resume attachment (its link expires after seven days), parse it, score it, then post a note with POST /v3/notes and apply a tag.

Field mapping

Where HireLayer results go in Greenhouse

Greenhouse candidates have no native skills field, and arrays sent with PATCH /v3/candidates/{id} replace the whole list: read the current values before adding to them.

HireLayer fieldGreenhouse Harvest v3Note
score + summary + evaluated_criteriaPOST /v3/notes (body, visibility)What recruiters read
score ≥ your thresholdPOST /v3/applied_candidate_tagsCreate the tag once with /v3/candidate_tags
info_candidate.job_titletitle (PATCH /v3/candidates/{id})
work_experiences[]POST /v3/candidate_employments
educations[]POST /v3/candidate_educations
skills[].skill_titlecustom_fields or tagsNo native skills field

Example

A web hook handler in TypeScript

A minimal Node.js handler: it checks the Greenhouse signature, parses the resume, scores it with criteria you stored for the job, and posts a private note. Add your own storage for criteria and your retry logic.

greenhouse-webhook.tstypescript
import { createHmac, timingSafeEqual } from 'node:crypto'

const HIRELAYER = 'https://hirelayer.co'
const headers = { 'X-API-Key': process.env.HIRELAYER_API_KEY! }

export async function handle(rawBody: string, signature: string) {
  // Greenhouse: "sha256 <hex>" over the raw body
  const expected = 'sha256 ' + createHmac('sha256', process.env.GH_WEBHOOK_SECRET!)
    .update(rawBody).digest('hex')
  const valid = signature.length === expected.length &&
    timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
  if (!valid) return 401

  const { payload } = JSON.parse(rawBody)
  const application = payload.application
  const resume = application.candidate.attachments
    .find((a: { type: string }) => a.type === 'resume')
  if (!resume) return 200

  // 1. Parse the resume (about 35 s)
  const file = await fetch(resume.url).then((r) => r.blob())
  const form = new FormData()
  form.append('file', file, resume.filename)
  form.append('application_id', String(application.id))
  const parsed = await fetch(`${HIRELAYER}/api/v3/parser`, {
    method: 'POST', headers, body: form, signal: AbortSignal.timeout(150_000),
  }).then((r) => r.json())

  // 2. Score with the criteria stored for this job
  const criteria = await loadCriteria(application.jobs[0].id)
  const match = await fetch(`${HIRELAYER}/api/v1/matching/job-candidate`, {
    method: 'POST',
    headers: { ...headers, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      job_text: criteria.jobText,
      candidate_text: parsed.info_resume.text,
      matching_criteria: criteria.items,
    }),
  }).then((r) => r.json())

  // 3. Write back to Greenhouse (Harvest v3)
  await fetch('https://harvest.greenhouse.io/v3/notes', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${await greenhouseToken()}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      candidate_id: application.candidate.id,
      body: `HireLayer score: ${match.score}\n${match.summary}`,
      visibility: 'private',
      note_type: 'NOTE',
    }),
  })
  return 200
}

Limits

Good to know

  • Harvest v3 only

    Greenhouse removed Harvest v1 and v2 on August 31, 2026. Use v3 and OAuth client credentials; the old API tokens no longer work.

  • Answer the web hook fast

    Parsing takes about 35 seconds. Acknowledge the web hook first and do the work in a queue or a background job, so Greenhouse does not retry a request that already succeded.

  • Greenhouse already parses resumes

    Greenhouse fills basic fields when a resume is uploaded (files up to 2.5 MB). Use HireLayer for scoring, normalized skills and structured history, not to replace the built-in parse.

  • Not a marketplace app

    HireLayer is not listed in the Greenhouse partner directory. You connect it through your own Harvest credentials, or ask us to build the connector with you.

FAQ

HireLayer and Greenhouse: questions

Does HireLayer integrate with Greenhouse?

Yes, through Greenhouse’s web hooks and the Harvest v3 API: your service receives each new application, calls HireLayer, and writes the score back as a note and tags. HireLayer has no Greenhouse marketplace listing.

Can I screen Greenhouse applicants with AI?

Yes. HireLayer turns the job description into weighted criteria, then scores each applicant from 0 to 1 with an explanation per criterion. The score supports your recruiters’ review; it does not reject anyone automatically.

Can I connect Greenhouse without writing code?

Yes, with a workflow tool such as n8n or Make: receive the Greenhouse web hook, send the resume to HireLayer from an HTTP step, then post the note with the Harvest v3 API. Greenhouse also has a Zapier app with a New Candidate Application trigger and a Create Candidate Note action.

Which Greenhouse permissions are needed?

A user who can manage API credentials and web hooks in the Dev Center. The Harvest v3 credentials need the scopes for attachments, notes and tags at least.

How many credits does one application use?

One credit to parse the resume and one to score it. Criteria are extracted once per job for one more credit, then reused for every applicant.

Connect Greenhouse to HireLayer today

The Free plan includes 50 credits a month, no card required. One successful call is one credit, on every API.