Skip to content

Products

HireLayer Talent Pool Search

Find the resumes closest to a job in your resume database, filtered by location and date added, in one call.

HireLayer Talent Pool Search finds, in the resume database of a workspace, the resumes closest to a job: every resume parsed or scored there is searchable. One POST /api/v4/resumes/search call with a stored job_id or a job text returns up to 500 application_ids sorted by closeness, with a similarity and whether each one is already scored for the job, for 1 credit per search. A job whose text replaces a stored job (same job_id) has its stored scores evaluated again, 1 credit each, and the search is refused (403) when the credits left do not cover them. A job text identical to the stored job returns the job as stored: a title sent with it is ignored; change it with PUT /jobs/{job_id}. Filter by location (a city and a radius) and by date added.

The search does not evaluate or explain: send the resumes you choose to the Resume Scorer by their application_id. Those already scored for the job, or being scored, cost nothing, unless their score is stale or its verdict was reset.

Endpoint
POST /api/v4/resumes/search
Input
A job_id or a job text, a limit, optional filters
Output
Resume ids, closest first
Price
1 credit per search; 1 credit per stored score evaluated again when a new text replaces a stored job
POST/api/v4/resumes/search

Finds in the workspace's resume database the resumes closest to a job, to choose which ones to score. Proximity only: no evaluation, no explanation. Score the chosen ones with POST /resumes/score.

Authentication
X-API-Key header
Billing
1 credit per search; 1 credit per stored score evaluated again when a new text replaces a stored job
Client timeout
Client timeout ≥ 60 s

Headers

  • HireLayer-Workspacestring

    Your customer's workspace id. Case-insensitive, created on first use. Absent, calls use default.

Request body

Content type application/json

Send exactly one of job_id or job.

  • job_idstring

    Letters, digits and . _ : ~ -, up to 200 characters.

  • jobobject

    A job not stored yet; it is stored, as by POST /jobs/extract-criteria.

    ›Show 3 child fields
    • textstringrequired

      1–50,000 characters

    • titlestring

      ≤ 300 characters

    • job_idstring

      Store the job under your own id.

  • limitinteger

    1–500 · default 50

  • filtersobject
    ›Show 2 child fields
    • locationobject

      Resumes whose location is unknown are left out when this filter is set.

      ›Show 3 child fields
      • citystringrequired
      • country_codestring

        ISO 3166-1 alpha-2, such as FR. Helps when a city name exists in several countries.

      • radius_kminteger

        1–500 · default 30

    • added_afterstring (date-time)
  • do_not_store_databoolean

    Enterprise plan only, else 403 enterprise_plan_required: process without storing anything. See Storage.

    default false

Response

200The closest resumes, closest first.

  • request_idstring

    The call's id, also in the HireLayer-Request-Id header. Quote it when contacting support.

  • job_idstring
  • resultsobject[]
    ›Show 4 child fields
    • rankinteger

      ≥ 1

    • application_idstring
    • similaritynumber

      Proximity to the job. Compare it only within one search; it is not a score.

      0–1

    • already_scoredboolean

      Already scored for this job, or being scored (pending); scoring it again costs 0 unless the score is stale or its verdict was reset.

  • credits_usedinteger

    Credits this call cost.

    ≥ 0

Errors

  • 400
    invalid_requestjob_id or job is required.

    param: job_id. Neither job_id nor job, or both.

    Fix, then retry

  • 400
    invalid_requestjob.text is required.

    param: job.text. job without its text.

    Fix, then retry

  • 400
    invalid_requestlimit must be an integer from 1 to 500.

    param: limit. limit out of range.

    Fix, then retry

  • 400
    invalid_requestNo city named Lyonn: check the spelling, or add country_code.

    param: filters.location.city. A filter breaks a rule (here a city not found): param names it.

    Fix, then retry

  • 400
    invalid_requestjob_id must contain letters, digits and . _ : ~ -, up to 200 characters.

    param: job_id. job_id is not a valid id.

    Fix, then retry

  • 400
    invalid_requestUnknown field lang.

    param: lang. A field the call does not take.

    Fix, then retry

  • 400
    invalid_requestThe request body is not valid JSON.

    The body is not valid JSON, not an object, or not sent as application/json.

    Fix, then retry

  • 400
    invalid_requestHireLayer-Workspace must contain letters, digits and . _ : ~ -, up to 200 characters.

    param: HireLayer-Workspace. HireLayer-Workspace is not a valid id.

    Fix, then retry

  • 400
    storage_requiredA search reads the stored resumes and jobs: it is not available without storage.

    param: do_not_store_data. do_not_store_data: true (Enterprise plan): a search needs storage.

    Do not retry

  • 400
    storage_requiredThis workspace runs without storage (do_not_store_data): a search reads the stored resumes and jobs, so it is not available in it.

    param: HireLayer-Workspace. The workspace runs without storage.

    Do not retry

  • 401
    missing_api_keyThe X-API-Key header is missing.

    No X-API-Key header.

    Fix, then retry

  • 401
    missing_api_keyAuthorization: Bearer is not accepted: send the key in the X-API-Key header.

    The key sent as Authorization: Bearer: it goes in X-API-Key.

    Fix, then retry

  • 401
    missing_api_keyThe key goes in the X-API-Key header, not in the URL.

    The key sent in the URL: it goes in X-API-Key.

    Fix, then retry

  • 401
    invalid_api_keyInvalid API key: it is unknown, malformed or revoked.

    The key is unknown, malformed or revoked.

    Fix, then retry

  • 403
    insufficient_creditsThis search needs 1 credit and none is left. Nothing was processed or billed.

    No credit left for the search (and for the stored scores a new job text evaluates again).

    Fix, then retry

  • 403
    enterprise_plan_requireddo_not_store_data is available on the Enterprise plan only. Nothing was processed or billed.

    param: do_not_store_data. do_not_store_data: true below the Enterprise plan.

    Do not retry

  • 404
    not_foundNo job req-7 in workspace default.

    param: job_id. No job under job_id in the workspace.

    Do not retry

  • 413
    payload_too_largejob.text must be 50,000 characters or less.

    param: job.text. The job text is over 50,000 characters.

    Fix, then retry

  • 500
    internal_errorInternal error: retry later. If it persists, contact support with the request_id.

    An unexpected error.

    Retry with backoff

  • 502
    model_unavailableThe analysis did not complete after several attempts. Nothing was stored or billed: retry with backoff.

    The analysis did not complete.

    Retry with backoff

  • 502
    internal_errorThe service could not be reached: retry later.

    The service could not be reached.

    Retry with backoff

  • 503
    internal_errorThe credit service is briefly unavailable: retry in a second.

    The credit service is briefly unavailable. Header Retry-After: <seconds>.

    Retry with backoff

  • 503
    internal_errorThe location filter is briefly unavailable: search without it, or retry later.

    param: filters.location. The location filter is briefly unavailable. Header Retry-After: <seconds>.

    Retry with backoff

  • 504
    internal_errorThe service did not answer in time. The change may still be applied: read it before sending it again.

    No answer in time.

    Retry with backoff

Behavior

Credits
1 per search. A job whose text replaces a stored job (same job_id) has its criteria extracted again, as POST /jobs/extract-criteria does: its stored scores are evaluated again in the background, 1 credit each, and the call is refused (403) when the credits left do not cover them and the search. That check asks for the worst case, every stored score of the job evaluated again; only the evaluations that actually run are billed.
A stored job sent again
a job whose text is the stored job's is used as it is, and its title is then ignored: change it with PUT /jobs/{job_id}.
Without storage
not available (400 storage_required), since there is no resume database.
# Example ids: replace job_30cfa454c97663f3e1801e5a61b87d74 with a job_id returned by POST /api/v4/jobs/extract-criteria.
curl -X POST https://hirelayer.co/api/v4/resumes/search \
  -H "X-API-Key: $HIRELAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "job_id": "job_30cfa454c97663f3e1801e5a61b87d74",
    "limit": 20,
    "filters": {
      "location": {
        "city": "Paris",
        "radius_km": 30
      }
    }
  }'
{
  "request_id": "2b8e6d14-7a3c-4f91-8e25-6c0d9b3f1a47",
  "job_id": "job_30cfa454c97663f3e1801e5a61b87d74",
  "results": [
    {
      "rank": 1,
      "application_id": "file_2c982f413a5e9e79563f8a1fcb5c7caa",
      "similarity": 0.81,
      "already_scored": true
    },
    {
      "rank": 2,
      "application_id": "cand-1042",
      "similarity": 0.77,
      "already_scored": false
    }
  ],
  "credits_used": 1
}