API reference navigation
POST /v1/searches/compile

Compile a role brief into a search config

Access
Authenticated
search:read
Cost
Free
Rate limit
60 / minute per account
Quota
None

Turn a pasted job description (plus optional context links and a steering prompt) into an editable SearchConfigV2 draft: the levers a search would run. Runs the role extractor and the deterministic lever compiler; no search runs and nothing is billed. Adopt the returned config, edit the levers, then execute. Links (jdUrl, jdLink, contextLinks) are recorded as context and are never fetched, so a link on its own is not enough to compile: send the JD text in jd, or the role in prompt. If briefTruncated comes back true, the extractor only read the first part of the brief.

Request body CompileSearchRequest

  • jd string | null

    The job description text, pasted in full. This is the primary signal the compiler reads.

    max 50000 chars
  • jdUrl string | null

    A link to the job posting. RECORDED as context and NEVER fetched, so a link on its own cannot compile: paste the text in `jd` or describe the role in `prompt`.

    max 2048 chars
  • jdLink string | null

    Alias for `jdUrl`. Same behaviour: recorded, never fetched.

    max 2048 chars
  • contextLinks array of string

    Extra reference URLs. Recorded as context; never fetched.

    max 20 items
  • links array of string

    Alias for `contextLinks`.

    max 20 items
  • prompt string | null

    Free-text steering, either instead of a job description or on top of one ("bias toward infra work, ignore the management line").

    max 50000 chars

Responses

  • 200 The compiled V2 draft
    • config object required

      The editable draft config. Nothing has been searched and nothing has been charged: review the levers, edit them, then send this to `POST /v1/searches/execute`.

      • version number required

        Marks this as a version 2 config. The only required field alongside `query`.

        2
      • query string | null required

        Free-text description of who you are looking for, matched semantically. This is the one field that carries the intent; every lever below narrows it.

        max 500 chars
      • entity string default: "auto"

        Which index to search. Leave `auto` to let the compiler route. Pin one when a lever you need landed in `unsupported`: `User` searches GitHub developers, `Repo` searches repositories and returns their contributors, and `LinkedInUser` searches the LinkedIn overlay, which covers only the minority of developers we hold a match for and therefore reaches a much smaller population.

        autoUserRepoLinkedInUser
      • requiredLanguages array of string default: []

        Programming languages that MUST be present, as a hard filter on repositories. This is the only language axis that hard-filters: `levers.skills` and `levers.technologies` are semantic aims. Set it only for languages you genuinely require, since it removes everyone else.

        max 20 items
      • earlyCareerSignals boolean default: false

        Bias the search toward people early in their career: adds a learning-in-public angle and inverts the devrank weighting, so established high-reputation accounts stop dominating the ranking.

      • aiFocusedSignals boolean default: false

        Bias every angle toward AI, agent, LLM, retrieval and inference work.

      • includeUnconventionalTitles boolean default: false

        Keep people whose job title is not a conventional engineering one but who ship code anyway. Leave false and the LinkedIn lane restricts to engineering functions.

      • levers object default: {}

        The narrowing levers. Every one is optional and every collection defaults to empty, so a query-only config is a legal search and you set only the axes you actually want to constrain. Check `appliedLevers` and `unsupported` on the response to see which of them actually bound.

        • skills array of string default: []

          Demonstrated abilities, matched against what the person has actually built. A semantic aim, not a hard filter — use `requiredLanguages` when something is genuinely mandatory.

          max 20 items
        • interests array of string default: []

          Topics and problem areas the person works on or gravitates toward. Distinct from `skills`, which is about demonstrated ability; the two are never collapsed. Setting this routes the search toward the repository lane.

          max 20 items
        • technologies array of string

          Languages, frameworks and systems, drawn from a CLOSED vocabulary — a value outside it is rejected rather than silently treated as free text. This is the concrete tooling axis; `skills` stays the conceptual one.

          max 20 items
        • location object

          Where the person is. Every location signal here is SELF-REPORTED by the developer and never verified.

          • countries array of string default: []

            Countries, matched against our geocoding of the self-reported location.

            max 20 items
          • cities array of string default: []

            Cities, matched against our geocoding of the self-reported location.

            max 20 items
          • states array of string default: []

            States or regions, matched against our geocoding.

            max 20 items
          • raw array of string default: []

            Raw location strings, matched against what the developer literally typed on GitHub.

            max 20 items
          • strict boolean

            True to hard-gate on location, trading recall for precision. False or unset applies it as a bias. Remember that location is self-reported and frequently stale or blank, so a hard gate drops everyone who left the field empty.

        • requireLinkedin boolean

          Return only developers we hold a LinkedIn match for. A severe narrowing: only a minority of the indexed GitHub population carries an overlay, so this trades most of the corpus for professional detail.

        • openToWork boolean

          Restrict to people flagged as open to work on their LinkedIn profile. Requires the LinkedIn overlay, so it implies the same narrowing as `requireLinkedin`.

        • experienceTier string

          A coarse experience band to aim at.

          earlyupToSeniorseniorall
        • yoeRange object

          A years-of-experience band, derived from the LinkedIn overlay, so it only constrains people we hold one for.

          • min integer | null required

            Minimum years of experience. Null for no lower bound.

            min 0
          • max integer | null required

            Maximum years of experience. Null for no upper bound.

            min 0
        • professional object

          Employment and education levers. Every one of these comes from the LinkedIn overlay, so setting any of them implicitly restricts the search to the minority of developers we hold a match for.

          • currentCompanies array of string default: []

            Companies the person works at NOW.

            max 20 items
          • pastCompanies array of string default: []

            Companies the person used to work at.

            max 20 items
          • mustHaveWorkedAt array of string default: []

            Companies the person must have worked at at some point, current or past. The either-or form of the two fields above.

            max 20 items
          • excludeCurrentCompanies array of string default: []

            Companies to exclude people currently working at. This is how you avoid sourcing out of your own company or a client’s.

            max 20 items
          • schools array of string default: []

            Institutions the person attended.

            max 20 items
          • titles array of string default: []

            Job titles to aim at.

            max 20 items
          • industries array of string default: []

            Industries the person works in.

            max 20 items
          • companySizeTier string

            The size band of the person’s current employer.

            1-5051-200201-20002000+
          • companiesMode string

            How the company lists bind. `exact` matches the named companies only. `similar` expands them to comparable companies, which widens reach at the cost of precision.

            exactsimilar
          • similarCompanies array of string default: []

            Companies to treat as reference points for "companies like these", rather than as an allowlist in themselves.

            max 20 items
          • includePast boolean

            Match against the full employment history rather than the current employer only. Defaults to true.

        • github object

          GitHub-side levers: stars, followers, seed repositories, and the devrank floor.

          • starRange object | null default: null

            A star band on the person’s repositories. Null, the default, means no bound at all rather than a missing value.

            • min integer | null required

              Lower bound, inclusive. Null for no lower bound.

              min 0
            • max integer | null required

              Upper bound, inclusive. Null for no upper bound.

              min 0
          • similarRepos array of string default: []

            Seed repositories, as `owner/name`. How they bind depends on `repoMode`: expanded to similar repositories, or matched exactly.

            max 20 items
          • contributedRepos array of string default: []

            Repositories the person COMMITS to rather than owns, as `owner/name`. This is how you find the people behind a repository they do not own — a company repo, or a large open-source project.

            max 20 items
          • minDevrank integer | null default: null

            A floor on devrank, the same 0–100 standing returned as `developer.stats.crackedScore`. Measured against the WHOLE indexed GitHub population rather than a peer group, so it is a blunt reputation gate and not a like-for-like comparison within a role. Null, the default, means no floor.

            min 0, max 100
          • hideHighProfile boolean

            Suppress very high-profile accounts, which otherwise dominate a ranking without being realistic hires.

          • repoMode string default: "similar"

            How `similarRepos` binds. `similar`, the default, expands each seed to comparable repositories. `exact` matches only the repositories you named.

            similarexact
          • followerRange object | null

            A band on GitHub follower count. Null bounds mean no limit on that side.

            • min integer | null required

              Lower bound, inclusive. Null for no lower bound.

              min 0
            • max integer | null required

              Upper bound, inclusive. Null for no upper bound.

              min 0
          • minContributionsLastYear integer | null

            THE DEAD-ACCOUNT GATE. A floor on GitHub contributions in the trailing 365 days; ANDs with minContributionsLastMonth when both are set. Recruiter Bot ships 100 here, and the absence of this floor is the single largest source of low-signal developers in a result set. This is NOT an index filter — the serving user index carries no activity column — so it is enforced after hydrate against a LIVE contribution-calendar read of the returned window only. Two consequences worth planning for: it narrows the page rather than the corpus (a tight floor can shorten a page, and countStatus reports it), and it is the one lever that costs a GitHub call, so an unset floor costs nothing at all. A developer GitHub did not answer for is KEPT, never dropped — the gate degrades open rather than emptying a page when the upstream is slow.

            min 0, max 100000
          • minContributionsLastMonth integer | null

            The trailing-28-day half of the dead-account gate, ANDed with minContributionsLastYear when both are set and answered by the same single live read. Recruiter Bot ships 20 here. Catches the developer who was active earlier in the year and has since gone quiet, which the yearly floor alone lets through.

            min 0, max 100000
      • filter object

        A raw filter expression, as an escape hatch for constraints the levers do not express. Opaque here and validated by the compiler; prefer the levers.

      • boost array of object default: []

        Signal weights that RE-RANK results. These never filter anyone out: the signals available here have too little coverage to be used as a hard gate, so they only reorder what already matched.

        max 20 items
        • signal string required

          The signal to weight. Read `GET /v1/search/capabilities` for the signals that exist and whether each can be pushed to the index.

          max 200 chars
        • weight number required

          Its weight. Positive favours the signal, negative penalises it.

      • rank object

        How to rank the results. Ranking today is page-local (see `rankScope` on the response), so this reorders the page rather than reaching deeper into the index.

        • preset string

          A named ranking preset.

          max 200 chars
        • weights array of object

          Explicit per-signal weights, as an alternative to a preset.

          max 20 items
          • signal string required

            The signal to weight.

            max 200 chars
          • weight number required

            Its weight.

    • summary string required

      A short plain-language readback of how the brief was interpreted, for a human to sanity-check before spending credits.

    • briefTruncated boolean

      True when the extractor could not read the whole brief and only succeeded on a shortened re-attempt, meaning the tail of your job description did not influence these levers. Absent means the whole brief was read.

  • 401 No or invalid credential
    • code string required

      Stable machine-readable error code. Branch on this, never on the numeric status.

      bad_requestunauthorizedsignature_requiredpayment_requiredforbiddennot_foundconflictgonepayload_too_largeunprocessable_entitytoo_many_requestsinternal_errornot_implementedbilling_unavailablenot_contactablemailbox_link_unavailablemailbox_requiredmail_engine_unavailablewebhook_publisher_unavailabledatabase_unavailableclient_error
    • message string required

      Human-readable explanation of the refusal.

    • status integer required

      The HTTP status code, repeated in the body.

    • remedy object

      A self-serve path forward, when one exists (a 402 points at the credit top-up).

      • kind string required

        What kind of remedy this is, so a client can route it: whether the caller can clear the condition through the API, or a person must act in the web app.

        topupconnect_mailbox
      • url string required

        Where to go to clear the condition: an API path, or a web app page when only a person can.

  • 403 Missing search:read
    • code string required

      Stable machine-readable error code. Branch on this, never on the numeric status.

      bad_requestunauthorizedsignature_requiredpayment_requiredforbiddennot_foundconflictgonepayload_too_largeunprocessable_entitytoo_many_requestsinternal_errornot_implementedbilling_unavailablenot_contactablemailbox_link_unavailablemailbox_requiredmail_engine_unavailablewebhook_publisher_unavailabledatabase_unavailableclient_error
    • message string required

      Human-readable explanation of the refusal.

    • status integer required

      The HTTP status code, repeated in the body.

    • remedy object

      A self-serve path forward, when one exists (a 402 points at the credit top-up).

      • kind string required

        What kind of remedy this is, so a client can route it: whether the caller can clear the condition through the API, or a person must act in the web app.

        topupconnect_mailbox
      • url string required

        Where to go to clear the condition: an API path, or a web app page when only a person can.