> ## Documentation Index
> Fetch the complete documentation index at: https://www.hirebase.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Export Jobs

> Start a task to export jobs using an existing search query and format

Export job search results using the same search parameters as `/v2/jobs/search`, but save the result as a downloadable file. This endpoint creates a task and returns its status and identifier. The user can poll the task using the [Get Task Status](/docs/api-reference/tasks/get-task-status) endpoint.

<Warning>
  This endpoint requires an API key for **all** requests. See [Authentication](/docs/authentication) to get one.
</Warning>

## Endpoint

```bash theme={null}
POST /v2/jobs/export
```

## Authentication

<ParamField header="x-api-key" type="string" required>
  Your Hirebase API key
</ParamField>

## Request Body

<Warning>
  Use `job_types` (plural) — `job_type` (singular) is silently ignored and your filter will not apply.
</Warning>

<Note>
  **Note:**

  * While some top-level request fields are required (such as search), the attributes within those fields are **optional**. You can include only the filters you need, for example, specifying just `job_titles` inside `search` is valid.
  * Filter combinations can be mixed and matched.
  * Use specific filters to narrow down search results and get relevant matches.
</Note>

<ParamField body="search" type="object">
  Parameters used to filter job search results

  `job_titles` and `keywords` support the same quoting, AND, and `-` exclusion syntax as the [Search Jobs](/docs/api-reference/jobs/search-post) endpoint.

  <Expandable>
    <ParamField body="job_titles" type="string[]">
      Array of job titles to search for.
    </ParamField>

    <ParamField body="keywords" type="string[]">
      Array of keywords matched against `description`, `technologies`, `skills`, and `benefits`.
    </ParamField>

    <ParamField body="job_board" type="string">
      Filter by the source job board (e.g., "iCIMS", "Lever", "Greenhouse").
    </ParamField>

    <ParamField body="location_types" type="string[]">
      Array of work arrangements. Accepted values: `"Remote"`, `"Hybrid"`, `"In-Person"`.
    </ParamField>

    <ParamField body="geo_locations" type="object[]">
      Array of structured location objects with `city`, `region`, and `country`.

      <Warning>
        ⚠️ Use `geo_locations` — a field named `locations` is **silently ignored**: the request succeeds but no location filtering is applied, and the export will contain jobs from everywhere. Since exports are metered, double-check this field name before running a large export.
      </Warning>

      <Expandable>
        <ParamField body="city" type="string">
          City name
        </ParamField>

        <ParamField body="region" type="string">
          State, region, or province
        </ParamField>

        <ParamField body="country" type="string">
          Country name
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="geofilter_params" type="object">
      Geographic filtering configuration, used together with `geo_locations`.

      <Expandable>
        <ParamField body="mode" type="string">
          Filtering mode for geographic search; '**auto**', '**weak**', '**strict**', '**box**' (defaults to: '**auto**'). Any other value returns a `422` validation error.

          * **Weak**: uses coordinate based matching
          * **Strict**: uses exact matching
          * **Box**: uses bounding box matching
          * **Auto**: uses heuristics to pick the optimal matching mechanism **(recommended)**
        </ParamField>

        <ParamField body="radius" type="number">
          Search radius for geographic filtering (defaults to **25.0**)
        </ParamField>

        <ParamField body="unit" type="string">
          Units for radius; '**mi**', '**km**', '**degrees**' (defaults to: '**mi**')
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="experience" type="string[]">
      Array of experience levels. Accepted values: `"Entry"`, `"Junior"`, `"Mid"`, `"Senior"`, `"Executive"`.
    </ParamField>

    <ParamField body="yoe" type="object">
      Years of experience range object.

      <Expandable>
        <ParamField body="min" type="number">
          Minimum years of experience
        </ParamField>

        <ParamField body="max" type="number">
          Maximum years of experience
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="company_name" type="string">
      Filter by specific [company name](/docs/api-reference/companies/search-companies)
    </ParamField>

    <ParamField body="company_slug" type="string">
      Filter by the unique [company slug](/docs/api-reference/companies/search-companies) (used for deep linking or specific company targeting).
    </ParamField>

    <ParamField body="salary" type="object">
      Salary range object.

      <Expandable>
        <ParamField body="min" type="number">
          Minimum salary
        </ParamField>

        <ParamField body="max" type="number">
          Maximum salary
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="job_types" type="string[]">
      Array of employment types. Accepted values: `"Full Time"`, `"Part Time"`, `"Contract"`, `"Internship"`.

      <Note>
        The `"Contract"` value matches roles whose returned `job_type` is `"Contract / Temporary"` — request token and response label differ.
      </Note>

      <Warning>
        The correct field name is **`job_types`** (plural). Using `job_type` (singular) is silently ignored — the request succeeds but the filter is not applied.
      </Warning>
    </ParamField>

    <ParamField body="job_category" type="string[]">
      Filter by one or more job category tags (e.g., `"Engineering Jobs"`, `"Marketing Jobs"`).
    </ParamField>

    <ParamField body="company_types" type="string[]">
      Filter jobs by the hiring company's headcount bucket. Accepted values: `"1-10"`, `"11-50"`, `"51-200"`, `"201-500"`, `"501-1000"`, `"1001-5000"`, `"5001-10000"`, `"10000+"`. Pass multiple values to combine ranges (e.g., `["11-50", "51-200"]`).

      <Note>
        This parameter is named `company_types` for historical reasons but currently filters by company size. A separate classification filter (Public Company / Non-Profit / etc.) will be added in a future API update.
      </Note>
    </ParamField>

    <ParamField body="industry" type="string[]">
      Filter by industry sector. Can be a single string or an array of strings. See [List Industries](/docs/api-reference/data/get-industries) for accepted values.
    </ParamField>

    <ParamField body="date_posted" type="string">
      The date when the job was posted. Format: YYYY-MM-DD
    </ParamField>

    <ParamField body="visa" type="string">
      Filter for jobs that offer visa sponsorship ("true" or "false")
    </ParamField>

    <ParamField body="sort_by" type="string">
      Field to sort results by. Accepted values: `"relevance"`, `"date_posted"`, `"salary"`, `"company"`, `"yoe"`. Invalid values are silently ignored.
    </ParamField>

    <ParamField body="sort_order" type="string">
      Sort direction (`"asc"` or `"desc"`).
    </ParamField>

    <ParamField body="currency" type="string">
      Currency code for salary filtering (e.g., "USD", "EUR").
    </ParamField>

    <ParamField body="days_ago" type="number">
      Filter jobs posted within the last specified number of days.
    </ParamField>

    <ParamField body="include_no_salary" type="string">
      Whether to include jobs that do not specify a salary ("true" or "false").
    </ParamField>

    <ParamField body="include_yoe" type="string">
      Whether to include jobs without explicit years of experience data ("true" or "false").
    </ParamField>

    <ParamField body="hide_recruiting_agencies" type="string">
      Set to `"true"` to exclude postings from recruiting/staffing agencies from the export.

      <Warning>
        ⚠️ Must be the **string** `"true"`. The boolean `true` is rejected with a `422` validation error.
      </Warning>
    </ParamField>

    <ParamField body="return_raw_description" type="string">
      Set to `"true"` to include a `description_raw` field in each exported record, containing the complete original HTML description from the source ATS (typically much longer than the cleaned `description`).

      <Warning>
        ⚠️ Must be the **string** `"true"`. The boolean `true` is rejected with a `422` validation error.
      </Warning>
    </ParamField>

    <ParamField body="page" default="1" type="number">
      Page number for pagination
    </ParamField>

    <ParamField body="limit" default="10" type="number">
      Determines the number of records exported (default `10`). Set high to export everything.

      <Note>
        **Note:**

        `limit` controls how many jobs are exported and defaults to `10`. To export your full result set, set `limit` to a high value (e.g. the `total_count` you get back from [`POST /v2/jobs/search`](/docs/api-reference/jobs/search-post) for the same filters). `page` selects the offset window in the usual way.
      </Note>
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="notify" type="boolean" default="false">
  Set to `true` to receive an email at your account address when the export completes, containing the download link. The flag is echoed back on the task object.
</ParamField>

<ParamField body="format" type="string" required>
  Export file format: `csv` or `json`.

  <Note>
    **`json` exports NDJSON** — newline-delimited JSON objects (one job per line), **not** a single JSON array. Parse line-by-line rather than calling `JSON.parse()` on the entire file. `csv` exports a standard comma-separated file.
  </Note>
</ParamField>

<Info>
  **Differences from `/v2/jobs/search`:** The `search` object accepts the same filters as [Search Jobs](/docs/api-reference/jobs/search-post), including `return_raw_description` and `hide_recruiting_agencies` — both are documented in the `search` object above. `limit` controls how many jobs are exported (default `10`) and `page` selects the offset window — set `limit` high to export your full result set.
</Info>

<Info>
  **Rate limit:** 100 requests per 60 seconds per API key. `429` responses include a `Retry-After` header. See [Error Handling](/docs/api-reference/errors).
</Info>

<Info>
  **Metering:** exports bill the jobs meter (`m_jobs_api_calls`) by the number of jobs exported: **`min(limit, total matches)`** is charged when the task is created and refunded if the task fails. Omit `limit` and every matching job is charged — use [`POST /v2/jobs/estimate`](/docs/api-reference/jobs/estimate) first to see the cost.
</Info>

## Flow

`POST /v2/jobs/export` returns a task immediately (`state: "queued"`). Poll [`GET /v2/tasks/{task_id}`](/docs/api-reference/tasks/get-task-status) until `state` is `"finished"` (or `"failed"`), then download from `result.download_url` before `result.expiry_time` (\~30 days). Set `notify: true` to get the link by email instead of polling.

## Response

Returns a task object representing the export job.

<Info>
  **Asynchronous workflow:** This endpoint returns immediately with a task object. Use the returned `id` to poll [`GET /v2/tasks/{task_id}`](/docs/api-reference/tasks/get-task-status). When `state` becomes `"finished"`, the `result.download_url` field will contain the URL to fetch your exported file.

  **Heads-up:** `limit` controls how many jobs are exported and **defaults to `10`**. To export your full result set, set `limit` to a high value (e.g. the `total_count` returned by [`POST /v2/jobs/search`](/docs/api-reference/jobs/search-post) for the same filters). `page` selects the offset window in the usual way.
</Info>

<ResponseField name="id" type="string">
  Unique task ID

  <Note>
    **Note:**

    Use this task ID to check the export status using the [Get Task Status](/docs/api-reference/tasks/get-task-status) endpoint and download the result once it’s ready.
  </Note>
</ResponseField>

<ResponseField name="type" type="string">
  Type of the task, always `"export_job_data"` for this endpoint
</ResponseField>

<ResponseField name="state" type="string">
  Current state of the task (`queued`, `processing`, `finished`, `failed`)
</ResponseField>

<ResponseField name="progress" type="number">
  Task progress as a float between 0.0 and 1.0
</ResponseField>

<ResponseField name="created_at" type="string">
  ISO timestamp of task creation
</ResponseField>

<ResponseField name="updated_at" type="string">
  ISO timestamp of last update
</ResponseField>

<ResponseField name="started_at" type="string">
  ISO timestamp of when the task started, or `null`
</ResponseField>

<ResponseField name="completed_at" type="string">
  ISO timestamp of when the task completed, or `null`
</ResponseField>

<ResponseField name="user_id" type="string">
  ID of the user who initiated the task
</ResponseField>

<ResponseField name="error" type="string">
  Error message if the task failed, otherwise `null`
</ResponseField>

<ResponseField name="worker_id" type="string">
  ID of the worker that processed the task, or `null`
</ResponseField>

<ResponseField name="priority" type="integer">
  Task priority level (higher means more urgent)
</ResponseField>

<ResponseField name="input" type="object">
  Task input payload, including the search query and export `format`
</ResponseField>

<ResponseField name="result" type="object">
  Present only when the task is complete

  <Expandable>
    <ResponseField name="download_url" type="string">
      URL to download the exported file
    </ResponseField>

    <ResponseField name="file_size" type="integer">
      File size in bytes
    </ResponseField>

    <ResponseField name="record_count" type="integer">
      Total number of jobs exported
    </ResponseField>

    <ResponseField name="expiry_time" type="string">
      ISO timestamp when the download URL will expire
    </ResponseField>
  </Expandable>
</ResponseField>

## Exported Record Fields

Each record in the exported file contains the following fields:

`_id`, `application_link`, `company_data`, `company_link`, `company_logo`, `company_name`, `company_slug`, `date_posted`, `description`, `education_level`, `job_board`, `job_board_link`, `job_categories`, `job_slug`, `job_title`, `job_type`, `language`, `location_raw`, `location_type`, `locations`, `meta`, `meta_completeness`, `recruiter_agency`, `requirements_summary`, `score`, `skills`, `technologies`, `visa_sponsored`, `yoe_range`

<Note>
  `description_raw` is added to every record when `return_raw_description` is set to `"true"` in the `search` object.
</Note>

## Example Request

<CodeGroup>
  ```json Example Request theme={null}
  {
      "search": {
    "job_titles": ["Site/Civil Engineer"],
    "geo_locations": [{"city": "Richmond", "region": "Virginia", "country": "United States"}],
    "yoe": {"min": 1, "max": 6},
    "company_name": "CompanyXYZ",
    "job_types": ["Full Time"],
    "industry": ["Design", "Construction"],
    "visa": "true",
    "sort_by": "relevance",
    "sort_order": "desc",
    "page": 1,
    "limit": 10
  },
    "format": "json"
  }
  ```
</CodeGroup>

## Example Response

<CodeGroup>
  ```json Example Response theme={null}
  {
      "id": "7700n868-05b7-4763-af74-e2c789c3260d",
      "type": "export_job_data",
      "state": "queued",
      "progress": 0.0,
      "created_at": "2025-06-13T06:10:07.605259",
      "updated_at": "2025-06-13T06:10:07.605260",
      "started_at": null,
      "completed_at": null,
      "user_id": "27893d278da3e42f2878gh90",
      "error": null,
      "worker_id": null,
      "priority": 0,
      "input": {
          "query": {
              "job_titles": [
                  "Site/Civil Engineer"
              ],
              "keywords": null,
              "location_group": null,
              "location_types": [
                  "In-Person"
              ],
              "geo_locations": [
                  {
                      "city": "Richmond",
                      "region": "Virginia",
                      "country": "United States"
                  }
              ],
              "experience": null,
              "yoe": {
                  "min": 1.0,
                  "max": 6.0
              },
              "include_yoe": null,
              "company_types": null,
              "company_name": "CompanyXYZ",
              "date_posted": null,
              "days_ago": null,
              "month": null,
              "salary": null,
              "include_no_salary": null,
              "currency": null,
              "job_types": [
                  "Full Time"
              ],
              "job_category": null,
              "industry": [
                  "Design",
                  "Construction"
              ],
              "sub_industry": null,
              "visa": "false",
              "include_expired": null,
              "hide_seen_jobs": null,
              "user_id": null,
              "company_slug": null,
              "job_slug": null,
              "job_board": null,
              "sort_by": "relevance",
              "sort_order": "desc",
              "page": 1,
              "limit": 10
          },
          "format": "json"
      },
      "result": null
  }
  ```
</CodeGroup>

## Error Responses

<AccordionGroup>
  <Accordion title="401 Unauthorized">
    Returns when the API key is missing, invalid, or incorrect.
  </Accordion>

  <Accordion title="403 Forbidden">
    Returns when your account does not have permission to access the requested feature.

    * This usually means the feature is restricted to certain subscription tiers.
  </Accordion>

  <Accordion title="422 Unprocessable Entity Error">
    Returns when the request contains invalid or improperly formatted data.

    * Occurs when the industry field is missing, not a string, or doesn't match any value from the list of valid industries.
    * May result from JSON decoding errors, such as malformed JSON or incorrect data types in the request body.
  </Accordion>

  <Accordion title="500 Internal Server Error">
    Returns when an unexpected error occurs on the server.

    * Also occurs during unhandled server-side failures or bugs that prevent the request from being processed.
  </Accordion>
</AccordionGroup>
