_private/qwestly-hire-docs/external-jobs-search-api.md

External Jobs Search API

This document is for integrators (e.g. contractors or partner services) that need server-to-server access to Qwestly Hire job data. It describes authentication, endpoints, query parameters, and response shapes for the Job Search API.

Overview

  • Purpose: Search and retrieve job postings stored in Qwestly Hire.
  • Protocol: HTTPS only. GET requests only.
  • Format: JSON request/response bodies (UTF-8).
  • Intended use: Backend services calling the Hire app origin you were given (not end-user browsers). Keep API keys on the server.

Base URL

All paths below are relative to the Hire application origin (for example https://hire.example.com).

{ORIGIN}/api/external/search/jobs

Replace {ORIGIN} with the environment-specific base URL provided by Qwestly (production, staging, etc.).

Authentication

Every request must include a valid Hire integration API key (HIRE_APP_API_KEY on the Hire deployment). This is the same secret used for other /api/external/* routes (e.g. company search and persist). There is no separate job-search key.

You can send the key in any one of these ways:

Method Header Value
Bearer Authorization Bearer <your-api-key>
ApiKey Authorization ApiKey <your-api-key>
API key header X-API-Key <your-api-key>

Unauthorized requests receive HTTP 401 with a null JSON body.

Security:

  • Do not commit keys to source control, embed them in client apps, or log them.
  • Request a key rotation from Qwestly if a key may be exposed.

Endpoints

1. List and search jobs

GET /api/external/search/jobs

Returns a paginated list of jobs. Supports filtering and optional full-text search.

Query parameters

Parameter Required Default Description
page No 1 Page number (integer ≥ 1).
limit No 50 Page size (integer ≥ 1, maximum 200).
status No active Job status. Typical values: draft, active, inactive, filled, expired.
company_id No Filter by company. Must be a MongoDB ObjectId string (24 hex characters).
job_family No Filter by job family, e.g. engineering, design, product, other.
location_type No Filter by work arrangement: remote, hybrid, in-person.
search No Full-text search string. When present, results are sorted by text relevance score, then updated_at, then _id.

Full-text search (search): The index covers fields such as title, description, company name, and structured requirement fields (e.g. skills and experience under must_have / nice_to_have). Use concise search terms as you would in a job board search box.

Success response — 200 OK

{
  "success": true,
  "data": [ /* array of job objects — see [Job object](#job-object) */ ],
  "pagination": {
    "totalCount": 0,
    "totalPages": 0,
    "currentPage": 1,
    "limit": 50
  }
}

Error responses

Status When
400 Invalid page, limit, or company_id format. Body: { "error": "<message>" }.
401 Missing or invalid API key. Body: null.
500 Server error. Body: { "error": "<message>", "details": "<message>" }.

Example (curl)

curl -sS \
  -H "Authorization: Bearer YOUR_HIRE_APP_API_KEY" \
  "https://{ORIGIN}/api/external/search/jobs?page=1&limit=20&status=active&search=typescript"

2. Get one job by ID

GET /api/external/search/jobs/{jobId}

Returns a single job when you already know its identifier.

Path parameters

Parameter Description
jobId MongoDB ObjectId of the job (24 hex characters).

Success response — 200 OK

{
  "success": true,
  "data": { /* single job object — see [Job object](#job-object) */ }
}

Error responses

Status When
400 jobId is not a valid ObjectId. Body: { "error": "Invalid jobId format" }.
401 Missing or invalid API key. Body: null.
404 No job with that ID. Body: { "error": "Job not found" }.
500 Server error. Body: { "error": "<message>", "details": "<message>" }.

Example (curl)

curl -sS \
  -H "Authorization: Bearer YOUR_HIRE_APP_API_KEY" \
  "https://{ORIGIN}/api/external/search/jobs/507f1f77bcf86cd799439011"

Job object

Each job in data is a JSON object. Identifiers are returned as strings where applicable. Dates are ISO 8601 strings when present.

Field Type Notes
_id string Job document id.
source_id string | null Internal source reference.
status string e.g. active, draft, …
title string Job title.
location string[] Location strings (may be empty array).
location_type string | null remote, hybrid, in-person.
employment_type string | null e.g. full-time, contract, …
company_name string | null
company_id string | null
org_unit_name string | null
org_unit_id string | null
parent_org_id string | null
exploratory_job_id string | null
job_family string | null e.g. engineering, design, …
is_epd boolean | null
has_equity boolean | null
equity_details string | null
benefits string | null
compensation object | null May include salary ranges and currency.
team string | null
description string | null Full description.
responsibilities string[]
must_have object | null Requirements structure (skills, experience, etc.).
nice_to_have object | null Preferred requirements.
metadata object | null Arbitrary extra fields.
hm_additional_info string | null Hiring manager notes.
llm_role_summary string | null Internal summary field when present.
is_publicly_accessible boolean Whether the job may be shown without an account.
created_at string | null ISO 8601.
updated_at string | null ISO 8601.

Field availability depends on what was stored for each job; many optional fields may be null.


Operational notes

  • Migration: If you previously used JOB_SEARCH_API_KEY, configure HIRE_APP_API_KEY to the same value (or rotate to one shared integration secret) and send that key on all /api/external/search/jobs requests. Remove JOB_SEARCH_API_KEY from Hire environment variables.
  • Pagination: Use totalCount, totalPages, currentPage, and limit to implement paging in your integration.
  • Sorting: Without search, jobs are ordered by updated_at descending, then _id ascending. With search, text relevance is applied first.
  • Support: For base URL, credentials, or access issues, contact your Qwestly project contact.

Changelog

Date Change
2025-03-26 Initial contractor documentation for /api/external/search/jobs.
2026-03-26 Authentication unified on HIRE_APP_API_KEY (same as other /api/external/* routes). JOB_SEARCH_API_KEY removed.