Skip to content

How to Export Data from Greenhouse: Methods, API Limits & Gaps

Complete guide to exporting data from Greenhouse: UI reports, Harvest API v3 rate limits, BI Connector, attachment expiry traps, and what data you can't get out.

Nachi Raman Nachi Raman · · 19 min read
How to Export Data from Greenhouse: Methods, API Limits & Gaps
TALK TO AN ENGINEER

Planning a migration?

Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.

Schedule a free call
  • 1,500+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing
  • Project success responsibility
  • Post-migration support included

How to Export Data from Greenhouse: Methods, API Limits & Gaps

Greenhouse gives you several paths to get data out: UI-based CSV report exports, the Harvest API, the Business Intelligence Connector, and secondary methods including GDPR data exports and webhooks. The right method depends on whether you need a one-time snapshot, a recurring data pipeline, or a full-fidelity extraction that preserves the relational structure between Candidates, Applications, Jobs, and Scorecards.

The short version: Greenhouse offers two primary ways to get data out — manual CSV exports and the Harvest API. Manual exports work for one-off analysis. The Harvest API is what you use for automated, repeatable pipelines. The Business Intelligence Connector adds a third option for enterprise analytics. CSV exports flatten your data model, strip scorecard attribute ratings, and silently drop attachment files. The Harvest API preserves relational integrity but enforces aggressive rate limits. The BI Connector gives you raw SQL access but runs on a nightly cadence.

This guide covers every extraction method, the real API constraints, what data you can and can't get out, and where teams consistently lose data.

Warning

Harvest API v1 and v2 will be deprecated and unavailable after August 31, 2026. Make sure existing custom integrations use the latest version of Harvest (v3) by this date and any new integrations are developed with v3. Do not invest engineering time in v1/v2 extraction scripts.

Greenhouse Data Model: What You're Actually Exporting

Before choosing an extraction method, understand what's inside the system. Greenhouse's core data model follows this hierarchy: Candidate → Application → Job → Scorecard.

Greenhouse is strictly application-centric. A Candidate has a single profile containing basic contact information. But all pipeline stages, interview schedules, rejections, and offers are tied to the Application, not the Candidate. A candidate who applied for Software Engineer in 2022 and Engineering Manager in 2024 has two separate Applications with independent histories.

This relational chain — Candidate → Application → Job → Scorecard — is the first thing that breaks when you flatten to CSV.

Key entities you'll need to extract:

Entity What It Contains Export Complexity
Candidates Name, email, phone, tags, source, custom fields Low
Applications Status, rejection reason, current stage, applied-at timestamp, source Medium
Jobs Title, status, departments, offices, openings, hiring team Low
Scorecards Overall recommendation, attribute ratings, questions, interviewer, submitted_at High
Attachments Resumes, cover letters, work samples High (signed URLs)
Offers Offer details, status, start date, custom offer fields Medium
Activity Feed / Notes Recruiter notes, emails, internal comments High
Custom Fields Org-specific fields at candidate, application, job, and offer level Medium

Any extraction plan should start with a decision about whether you need the relational chain intact. If you do, CSV exports are off the table.

Method 1: UI Report Exports (CSV)

How It Works

Greenhouse's built-in reporting lets you run essential reports (pipeline, time-to-hire, source effectiveness) and custom reports, then export results as CSV or Excel. Recipients receive an email containing the report data, a link to view the report in Greenhouse Recruiting, and a downloadable .csv version of the report. You can also schedule a report email at a regular cadence. Scheduling options include weekly, bi-weekly, monthly, and quarterly frequency.

The in-app essential candidate report is limited to 1,000 candidate applications, and its grain is the application row, not the full candidate-to-application relationship model. (support.greenhouse.io)

Greenhouse also offers a Report Connector that pulls reports into Google Sheets with automatic refresh. Refreshes overwrite the sheet's imported data, making it useful for live dashboards but not as a system of record. (support.greenhouse.io)

What You Get

  • Candidate lists with basic profile fields
  • Pipeline snapshots filtered by job, department, or office
  • Source attribution data
  • Custom field values (if included in the report configuration)

What You Lose

  • Scorecard attribute-level ratings — CSV reports capture overall recommendation but flatten or omit per-attribute scores
  • Relational IDs — the Candidate → Application → Job chain is collapsed into rows, with no reliable foreign key to rejoin them
  • Attachments — resumes and documents are not included in CSV exports
  • Activity feed / notes — not available through standard report exports
  • Interview scheduling details — panel composition, times, feedback links

One additional trap: if you need candidate responses to custom application questions for a specific job post, you must choose Email as XLS. The standard in-app view does not include those responses. (support.greenhouse.io)

When to Use It

One-off analysis, ad-hoc stakeholder reporting, or small-scale audits. Not viable for migration, data warehouse pipelines, or anything requiring relational integrity. If you're performing a full system migration — like a Greenhouse to Lever migration or a Greenhouse to Ashby migration — CSV exports are insufficient.

Info

Greenhouse has introduced "Download candidate data" and "Export reports" permissions that give organizations more control over how personal candidate information is shared outside the platform. If your export plan starts failing for some users and not others, check permissions before debugging code.

Method 2: Harvest API v3 (Full Programmatic Export)

The Harvest API is Greenhouse's primary extraction interface. It is designed to export internal candidate and job information from Greenhouse Recruiting via GET endpoints, and also includes POST, PUT, PATCH, and DELETE endpoints to transform information in Greenhouse Recruiting.

Authentication and Versioning

Harvest v1/v2 (deprecated August 31, 2026): Uses Basic Auth over HTTPS. The username is your Greenhouse API token and the password should be blank.

Harvest v3 (current): Requires Bearer Authorization over HTTPS, using a valid JWT access token. Harvest v3 also supports the full OAuth2 authorization code flow for partner integrations that connect to multiple Greenhouse accounts.

Scopes are granular — for example, harvest:applications:list to read applications, harvest:candidates:create to create candidates. List endpoints require a Site Admin authorizing user.

JWT token expiry: Greenhouse v3 access tokens expire after 1 hour (3,600 seconds). Your extraction pipeline must implement token refresh logic — either proactively before expiry or reactively on a 401 response — rather than using a long-lived secret. Store your refresh token separately and treat it as a privileged credential.

# v3 Bearer token request
curl --location 'https://harvest.greenhouse.io/v3/candidates?per_page=100' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'

Rate Limits

This is where most extraction scripts break. Greenhouse enforces rate limits in unusually short windows.

API Version Rate Limit Window Throttle Response
Harvest v1/v2 50 requests Per 10 seconds (rolling) HTTP 429
Harvest v3 75 requests (observed) Per 30 seconds (fixed) HTTP 429
v3 Token Issuance Throttled separately Per 60 seconds HTTP 429
Audit Log API 3 requests (additional sub-limit) Per 30 seconds HTTP 429

Important: Greenhouse does not publish a single universal v3 rate limit number in its documentation. The 75-per-30-second figure is derived from observed X-RateLimit-Limit response headers during live extractions and from documented examples in Greenhouse's developer materials — but Greenhouse reserves the right to adjust it. Some endpoints carry their own sub-limits independent of the general limit.

Build your rate limiter to read the X-RateLimit-Limit and X-RateLimit-Remaining response headers dynamically rather than hardcoding a number. Use exponential backoff starting at 1 second with a maximum of 30 seconds on any HTTP 429 response.

Rate limits are per API key, not per endpoint — two scripts sharing one key will collide. If you're running parallel extraction jobs (e.g., one for candidates, one for scorecards), use separate API keys or serialize requests through a single queue.

At the documented example rate of 50 requests per 10 seconds with 500 records per page, a nightly export of a 10,000-candidate org takes under a minute of request time for candidate records alone. Rate limits are not the primary bottleneck for structured data — attachments are.

Pagination

v1/v2: Paginated results include a Link (RFC-5988) response header with next, prev, and last URLs. Max per_page is 500.

v3: Harvest v3 uses cursor-based pagination for list endpoints. v3 currently returns only a next link — no prev or last. You cannot calculate total result counts or jump to arbitrary pages. Follow the rel="next" URL from the response Link header until it's absent.

Critical cursor rule: For v3, the cursor parameter must not be combined with other filter parameters. Apply your filters (created_at, updated_at, status) on the first request only.

# v3 cursor-based pagination — first request with filters
curl 'https://harvest.greenhouse.io/v3/candidates?updated_at[gte]=2026-01-15T00:00:00Z&per_page=500' \
  -H 'Authorization: Bearer TOKEN'
 
# Response Link header:
# Link: <https://harvest.greenhouse.io/v3/candidates?cursor=abc123>; rel="next"
 
# Subsequent requests — use the cursor URL directly, no additional params
curl 'https://harvest.greenhouse.io/v3/candidates?cursor=abc123' \
  -H 'Authorization: Bearer TOKEN'

Key Endpoints for Data Extraction

Endpoint Returns
GET /v3/candidates Candidate records with profile fields and application IDs
GET /v3/applications Application records with status, stage, job ID, rejection reason
GET /v3/jobs Job records with departments, offices, openings, hiring team
GET /v3/scorecards Scorecards with attribute ratings, questions, interviewer
GET /v3/offers Offer records with custom fields
GET /v3/scheduled_interviews Interview schedule with panel and times
GET /v3/custom_fields Custom field definitions
GET /v3/sources Source definitions for attribution

v3 list endpoints support created_at and updated_at filters with operators gte, lte, gt, and lt. Do not use both created_at and updated_at filters simultaneously on the same request.

Scorecard API Response Structure

Scorecards are the most complex entity to extract. A truncated v3 scorecard response looks like this:

{
  "id": 4897232,
  "application_id": 19284756,
  "interviewed_at": "2026-01-10T14:00:00.000Z",
  "submitted_at": "2026-01-10T16:32:00.000Z",
  "submitted_by": {
    "id": 834921,
    "name": "Jane Doe",
    "employee_id": "EMP-0042"
  },
  "overall_recommendation": "yes",
  "attributes": [
    {
      "name": "Communication",
      "type": "Skills",
      "note": "Articulates trade-offs clearly.",
      "rating": "yes"
    },
    {
      "name": "Problem Solving",
      "type": "Skills",
      "note": "Strong first-principles approach.",
      "rating": "strong_yes"
    }
  ],
  "ratings": {
    "strong_yes": ["Problem Solving"],
    "yes": ["Communication"],
    "mixed": [],
    "no": [],
    "strong_no": []
  },
  "questions": [
    {
      "id": 98234,
      "question": "Describe a system you designed under constraint.",
      "answer": "Redesigned the ingestion pipeline to handle 10x load..."
    }
  ]
}

Key fields for extraction:

  • application_id — the foreign key linking scorecards back to applications
  • attributes [].rating — per-attribute rating values: strong_yes, yes, mixed, no, strong_no
  • overall_recommendation — the top-level interviewer decision
  • questions [].answer — free-text interview notes, often the highest-value qualitative data

Attribute ratings are not present in CSV exports — you must use the API to get them.

The Attachment Trap

This is the single most common data-loss failure mode in Greenhouse exports.

Resumes, cover letters, and other document attachments in Greenhouse are hosted on Amazon Web Services and provided via signed, temporary URLs. These URLs expire after 7 days from the time of API retrieval, per Greenhouse's developer documentation. Users should download these documents immediately after the request is made and should not rely on these URLs to be available for future requests.

Greenhouse doesn't provide a bulk download feature. You must iterate through candidates or applications via API, extract each attachment URL, and download the file immediately.

import requests
import time
 
def download_attachments(candidate, output_dir):
    for attachment in candidate.get('attachments', []):
        url = attachment.get('url')
        filename = attachment.get('filename', f"attachment_{attachment.get('id', 'unknown')}")
        if url:
            resp = requests.get(url, stream=True)
            with open(f"{output_dir}/{filename}", 'wb') as f:
                f.write(resp.content)
        time.sleep(0.2)  # Stay within rate limits

Attachment type visibility rules: Not all attachment types are equally accessible. Resumes and cover letters are broadly accessible to users with candidate access. Offer packets, signed offer documents, and private documents have narrower access restrictions. Ensure your API key's associated user has the necessary permissions for each attachment type before assuming completeness.

Danger

In the event AWS S3 is experiencing issues, document attachments will not be available in Harvest. Plan for retry logic on attachment downloads — S3 outages and transient errors will cause silent data loss if you don't handle them. Implement at least 3 retries with exponential backoff before marking an attachment as failed.

Method 3: Business Intelligence Connector

The Business Intelligence Connector (BIC) is Greenhouse's warehouse export. Greenhouse delivers your data nightly to Amazon S3 or Amazon Redshift, spanning data from the creation of your environment. (support.greenhouse.io)

Greenhouse's own guidance is to use BIC for advanced reporting and APIs for real-time transactional integrations. (support.greenhouse.io)

Pros:

  • No rate limits. You query the data using standard SQL.
  • Historical stage transitions. You get access to underlying tables that are difficult to reconstruct via the REST API, including timestamps for each stage transition.
  • Zero extraction code. No pagination or retry logic required.

Cons:

  • Cost. BIC is an expensive add-on, available on Plus and Pro tiers.
  • Latency. Data is refreshed once every 24 hours. Not suitable for same-minute provisioning, trigger-based automation, or cutover-day delta syncs.
  • Schema complexity. The BIC schema is highly normalized, requiring complex SQL joins to reconstruct a candidate's full profile.

BIC Table Reference

The core BIC tables and their grain:

Table Grain Notes
candidates One row per candidate Snapshot; PII tables (email, phone, address) are opt-in
applications One row per application Latest-status snapshot only — no historical records
jobs One row per job Includes departments, offices, openings
scorecards One row per scorecard Includes attribute-level ratings
custom_fields One row per field definition Separate value tables per entity type
demographic_answers One row per answer Excludes EEOC responses
stage_transitions One row per transition event Historicized — this is the primary advantage over the REST API

Critical BIC schema notes:

  • The applications table is a latest-status snapshot — Greenhouse explicitly documents that it does not contain historical records. If you need application history over time, you must build your own snapshot layer on top of daily BIC exports.
  • Candidate email, mailing address, and phone number tables are opt-in and must be explicitly enabled in BIC configuration.
  • The demographic_answers table excludes EEOC responses. If your compliance or DEI reporting requires EEOC data, you must extract it separately via the Harvest API (GET /v3/applications/{id}/demographics).
  • Joining scorecards to candidates requires: scorecards → applications (via application_id) → candidates (via candidate_id). There is no direct candidate_id on the scorecards table.

If your goal is building internal dashboards in Tableau or Looker, the BI Connector is the best choice. If your goal is migrating data to a new ATS — see our Greenhouse to Workday migration guide — the Harvest API is preferred because it returns JSON that maps more directly to target system schemas.

Other Export Paths: GDPR Exports, Webhooks, and Third-Party Tools

GDPR Data Subject Request Export

Companies need to provide candidate data upon request in an efficient and easy format. Greenhouse has built a feature to respond to and complete data requests from candidates. You can configure what data should be accessible and send it to candidates in a CSV file by clicking a button on their profile.

This is designed for compliance, not bulk extraction. It exports a single candidate's data — useful for GDPR Article 15 access requests but not a viable method for migration or analytics.

Candidate packets serve a similar one-person purpose: configured in admin settings and downloaded from a candidate profile. If a packet includes private data, only users with private data access can download it. (support.greenhouse.io)

Webhooks for Real-Time Sync

Greenhouse supports webhooks for candidate and job events. Below is the complete list of supported webhook events versus notable gaps:

Supported webhook events:

Event Trigger
application_updated Application status changes
candidate_stage_change Candidate moves to a new pipeline stage
candidate_hired Recruiter clicks "Mark Candidate as Hired"
offer_created New offer created
offer_updated Offer details modified
offer_deleted Offer removed
job_post_created New job posting published
job_post_updated Job posting modified
delete_candidate Candidate profile deleted

Notable missing webhook events:

Missing Event Impact
candidate_created Cannot trigger on new candidate entry without polling
interview_scheduled No push notification when interviews are booked
scorecard_submitted Must poll for new scorecard submissions
application_created New inbound applications require polling to detect
note_created Activity feed additions are not pushed

These gaps mean a webhook-only strategy will miss significant event categories. For complete coverage, use webhooks for supported events plus a nightly full-diff poll for unsupported ones.

The candidate hired webhook fires each time someone clicks "Mark Candidate as Hired" and includes candidate, job, offer, and custom field data. It's a useful forward-sync mechanism for HRIS provisioning but does not replace a historical backfill. (support.greenhouse.io)

Third-Party Integration Platforms

Several iPaaS tools offer pre-built Greenhouse connectors that wrap the Harvest API:

  • Celigo — Greenhouse connector enables automating applicant and candidate workflows and connecting with other human resource management systems.
  • Skyvia — Load data from Greenhouse to CSV files with no code; exports Applications, Candidates, Jobs, etc. automatically on a schedule.
  • Fivetran / Improvado — ELT connectors that replicate Greenhouse data into cloud warehouses.

These tools abstract away pagination and rate-limit handling but still operate within the same Harvest API constraints. They won't give you data the API doesn't expose. They're a good fit for low-code teams who need simple scheduled exports, but offer less control over attachment downloads and edge-case handling.

What Data Can't You Export from Greenhouse?

No export method gives you everything. Here's what's missing or incomplete:

Data Export Gap
Email thread content Not available via Harvest API — only email metadata (timestamps, subject line)
Greenhouse internal analytics Calculated metrics (time-in-stage, pass-through rates) are report-level aggregations, not raw exportable fields
User permission configurations Org-level role/permission settings are not exposed via API
Deleted records Once a candidate or application is deleted, it's gone from the API — no soft-delete or archive endpoint
Interview kit templates Kit configurations are readable but the template structure does not fully export
Workflow/automation rules Stage-transition automations, auto-advance rules, and approval chains are not API-accessible
Candidate photos Candidate photos have been removed from Greenhouse and will no longer be accepted
Third-party assessment artifacts Take-home tests submitted through some partner integrations live behind a URL on the partner platform, not in Greenhouse attachments
EEOC demographic responses Excluded from BIC demographic_answers table; accessible only via GET /v3/applications/{id}/demographics

If you're migrating to another ATS, the workflow and automation gap is significant — you'll need to manually recreate stage configurations, approval flows, and email templates in your target system.

Building a Full Greenhouse Export Pipeline

Here's the extraction sequence we use for migration-grade exports:

Step 1: Inventory and Scope

Pull custom field definitions first (GET /v3/custom_fields). This tells you the shape of your data before you start extracting records. Count candidates, applications, and jobs to estimate total API calls and time. At 500 records per page, a 50,000-candidate org requires a minimum of 100 paginated requests for candidates alone — more if you're filtering by date range.

Step 2: Extract Reference Data

Export lookup tables before transactional data:

  • Jobs (with departments, offices, openings)
  • Sources
  • Users (interviewers, recruiters, coordinators)
  • Custom field option sets
  • Rejection reasons
  • Demographic question and answer definitions

These are small payloads with high join value. Without them, you'll have orphaned IDs in your candidate and application records that you can't decode downstream.

Step 3: Extract Candidates and Applications

Use updated_at filters for incremental extraction. On the first run, pull everything. On subsequent runs, pull only records updated since the last checkpoint.

# Incremental extraction pattern
last_sync = load_checkpoint()  # e.g., "2026-01-15T00:00:00Z"
url = f"https://harvest.greenhouse.io/v3/candidates?updated_at[gte]={last_sync}&per_page=500"
 
while url:
    resp = requests.get(url, headers=auth_headers)
    if resp.status_code == 429:
        time.sleep(exponential_backoff())
        continue
    if resp.status_code == 401:
        auth_headers = refresh_token()  # JWT expiry — renew and retry
        continue
    process_candidates(resp.json())
    # Download attachments inline — don't defer
    for candidate in resp.json():
        download_attachments(candidate, output_dir)
    url = parse_next_link(resp.headers.get('Link'))
 
save_checkpoint(datetime.utcnow().isoformat())

Recommended extraction order: jobs/openings → field dictionaries → candidates → applications → offers → attachments → notes → scorecards. That ordering minimizes foreign-key misses and makes validation less painful.

Step 4: Extract Scorecards and Interview Data

Scorecards are the highest-value, highest-complexity data. Each scorecard includes attribute-level ratings (see JSON structure above), free-text responses, and interviewer metadata. Pull them via GET /v3/scorecards and match to applications using application_id.

Filter by updated_at for incremental runs. Note that a scorecard's updated_at changes when an interviewer edits their feedback after initial submission — your pipeline should upsert, not insert-only.

Step 5: Download Attachments Synchronously

Do not store URLs for later download. Download each file as you encounter its URL. Store files with a naming convention that preserves the Candidate ID → Application ID → Attachment ID chain:

/{candidate_id}/{application_id}/{attachment_id}_{filename}

This naming convention makes it possible to reassemble the relational structure from the file system alone if your database metadata is lost.

Step 6: Validate

Compare record counts between Greenhouse UI reports and your extracted dataset. Check for:

  • Missing scorecards (common when API key permissions restrict access to certain interview types)
  • Orphaned applications (candidate deleted but application record cached in your extract)
  • Attachment download failures (S3 errors, expired URLs on retry)
  • Null PII fields (GDPR-anonymized candidates — see below)

Edge Cases That Break Greenhouse Exports

Custom Fields

Greenhouse allows administrators to create custom fields on Jobs, Candidates, Applications, and Offers. In the API payload, these appear in a custom_fields object keyed by field name. Administrators can change the names or types of these fields over time, which means the same key may represent different data across time periods. Your extraction script must dynamically inspect the field metadata (GET /v3/custom_fields) rather than hardcoding field names. Without the field definition metadata, you can't interpret the values in candidate or application records.

Merged Candidates

Recruiters frequently merge duplicate candidate profiles. When this happens, Greenhouse retains the primary candidate ID and aliases the secondary ID. If your extraction script uses a list of historical candidate IDs (from a previous snapshot, for example), it will throw HTTP 404 errors when attempting to fetch profiles that have been merged into another record. Always check for merged candidate references and resolve aliases before treating a 404 as a missing record.

GDPR-Anonymized Candidates

When a candidate is anonymized for GDPR or CCPA compliance, their PII is scrubbed, but historical application data remains for reporting purposes. Here is what the API returns for each field type after anonymization:

Field Anonymized Value
first_name null
last_name null
email_addresses [] (empty array)
phone_numbers [] (empty array)
addresses [] (empty array)
tags [] (empty array)
application.status Preserved
application.rejection_reason Preserved
scorecard.overall_recommendation Preserved

Your extraction schema must define all PII fields as nullable and your downstream system must handle empty arrays gracefully. A common failure mode is a database NOT NULL constraint on email that causes inserts to fail for anonymized candidates, silently dropping their application records from your extract.

Greenhouse Recruiting allows organizations to control the data retention timeframe, data to be deleted, and notifications on a per-office basis with Data Retention Rules. If you're extracting data near the end of a retention window, records may be auto-deleted before your export completes — run your extraction in a single continuous session rather than spread across days.

Private Notes and API Security

Private candidate notes can be accessed via the Harvest API as long as the credential has the relevant Activity Feed access, regardless of the end user's in-app permissions. This means an API key can retrieve notes that the human user associated with the key cannot see in the UI.

Pair that with attachment visibility rules — offer packets, signed offer documents, and private documents have narrower access than resumes or cover letters — and the takeaway is: treat export credentials as privileged infrastructure, not convenience keys. Scope API keys to the minimum required permissions and audit who has access to them. (support.greenhouse.io)

The On-Behalf-Of Header

All write operations (POST, PATCH) require an On-Behalf-Of: <greenhouse_user_id> header referencing an active Site Admin. Omitting it returns a 403. This matters if your export pipeline also writes back data (tags, notes, or status updates) during extraction — a common pattern in migration tooling that applies tags to mark records as exported.

Third-Party Assessment Artifacts

Take-home tests submitted through some third-party integrations are not added to the candidate's Greenhouse attachment list. The results live behind a URL on the partner platform. If your migration scope includes assessment artifacts, query each partner integration's API separately — do not assume every file associated with a candidate lives in Greenhouse. (support.greenhouse.io)

GDPR and CCPA Considerations

Exporting candidate data from Greenhouse triggers compliance obligations regardless of extraction method. The GDPR regulates the exportation of personal data outside of the European Union. Whether or not you are geographically located within the EU, GDPR impacts your organization as long as you are processing and storing personal data of individuals who live there.

Greenhouse-specific GDPR fields and their API locations:

Data Type API Location GDPR Classification
Name, email, phone GET /v3/candidates — top-level fields Personal data (Art. 4)
IP address (application) application.location.address Personal data
GDPR consent status candidate.gdpr_consents [] Consent record (Art. 7)
Anonymization status candidate.anonymized (boolean) Processing restriction (Art. 18)
Demographic answers GET /v3/applications/{id}/demographics Special category (Art. 9) if race/ethnicity included

Practical implications:

  • Data minimization: Don't export more than you need. If migrating, define a cutoff date — candidates older than 2–3 years with no activity often fall outside retention policy.
  • Right to erasure: People have the "right to be forgotten" and Greenhouse customers are required to erase a candidate's personal data when requested. If you export data and then receive an erasure request, you must delete it from your export destination too — your target system or data warehouse is not exempt.
  • Consent status: Export the gdpr_consents array alongside candidate records. Greenhouse tracks consent type, consent date, and consent source at the candidate level. Losing this during migration means you cannot demonstrate lawful basis for processing in the target system.
  • Cross-border transfer: If your export destination is outside the EU, ensure appropriate transfer mechanisms (Standard Contractual Clauses, adequacy decisions) are in place before the export begins — not after.
  • Anonymized candidate handling: Your target system must import anonymized candidates as anonymized. Do not reconstruct PII from backups or cached data for candidates who have been anonymized in Greenhouse.

For a deeper dive, see our GDPR & CCPA compliance guide for candidate data migration.

Choosing the Right Extraction Method

Scenario Recommended Method
One-time report for stakeholders UI CSV export
Recurring spreadsheet analysis Report Connector to Google Sheets
Warehouse analytics pipeline Business Intelligence Connector
Full ATS migration Harvest API v3 (full extract + attachments)
Individual GDPR data request Built-in GDPR export or candidate packet
Low-code team, simple sync Third-party connector (Celigo, Skyvia, Fivetran)
Real-time event capture Webhooks + nightly API poll
Downstream HRIS hire sync Candidate hired webhook or accepted-offer polling
EEOC demographic data Harvest API only — not available in BIC
Historical stage transition data Business Intelligence Connector (stage_transitions table)

For migrations specifically, the API-based path is the only one that preserves scorecard attribute ratings, attachment files, and the full Candidate → Application → Job relational chain. CSV exports will always lose fidelity. For migration-specific patterns, see our guides for Greenhouse to Lever, Greenhouse to Ashby, and Greenhouse to Workday.

Frequently Asked Questions

How do I export all candidate data from Greenhouse?
Use the Harvest API v3 to programmatically extract candidates, applications, scorecards, and attachments via GET endpoints. UI CSV exports only capture flat candidate lists without relational data, scorecard attribute ratings, or resume files. Authenticate with OAuth 2.0 Bearer tokens and paginate using cursor-based Link headers.
What are the Greenhouse Harvest API rate limits?
Harvest v1/v2 allows 50 requests per 10-second rolling window. Harvest v3 uses a 30-second fixed window with 75 requests as the documented example limit. Token issuance is throttled separately on a 60-second window. Some endpoints like the Audit Log API have additional sub-limits. Exceeding limits returns HTTP 429.
Can I bulk download resumes from Greenhouse?
No. Greenhouse does not provide a native bulk resume download feature. Resumes are served as signed AWS S3 URLs that expire after 7 days. You must use the Harvest API to iterate through candidate or application records and download each attachment file immediately — storing URLs for later will result in dead links.
Is Greenhouse Harvest API v1 being deprecated?
Yes. Greenhouse Harvest API v1 and v2 will be deprecated and unavailable after August 31, 2026. All new integrations should use Harvest v3 with OAuth 2.0 authentication. Existing v1/v2 integrations using Basic Auth must be migrated to v3 before the deadline.
What data can't be exported from Greenhouse?
Email thread content (only metadata is available), internal analytics calculations, user permission configurations, deleted records, workflow automation rules, stage-transition automations, approval chains, and third-party assessment artifacts that live on partner platforms are not accessible via the Harvest API or CSV exports. Candidate photos have been permanently removed from the platform.

More from our Blog