{"openapi":"3.1.0","info":{"title":"Vamo API","version":"1.0.0","description":"The Vamo API is the control plane for GitHub developer search and enrichment. Search for developers by what they have actually built, resolve GitHub or LinkedIn identities to full profiles, and enrich them with the signals you need.\n\n## Base URL\n\n```\nhttps://api.vamotalent.ai\n```\n\n## Authentication\n\nEvery non-public endpoint takes a bearer credential:\n\n```\nAuthorization: Bearer vamo_sk_...\n```\n\nAPI keys are prefixed `vamo_sk_` and are scoped to one account. Mint and manage them with the Keys endpoints (`POST /v1/keys`, `GET /v1/keys`, revoke). Humans signed in to the Vamo app use session tokens over the same header; keys and sessions follow one usage model.\n\nStatus codes are precise: `401` no or invalid credential, `403` your role lacks the required entitlement, `402` your plan lacks the capability, `429` a rate limit or usage quota is exhausted.\n\nEvery error body carries a stable `code`, a human `message`, and, when the condition is self-clearable, a `remedy` pointing at the way out. Branch on `code`, never on the numeric status.\n\n## Rate limiting\n\nEvery endpoint declares its own fixed-window rate limit, scoped per account, per actor, or per IP. The exact limit and window are in the operation's `x-vamo.rateLimit` block. Exceeding a limit returns `429`.\n\n## Versioning\n\nThe API is versioned in the path (`/v1`). Additive changes ship continuously and are not breaking: new endpoints, new optional request fields, and new response fields. Parse responses permissively and ignore fields you do not recognise.\n\n`openapi.json` is generated from the API itself, so it cannot lag behind the behaviour. Diff it in CI and you will see any change to the surface the moment it ships.\n\n## Quickstart\n\nSearch for developers by what they have built. Describe the work in plain language and get back a page of matching developers, each with the proof behind the match.\n\n```bash\ncurl -G https://api.vamotalent.ai/v1/developers/search \\\n  -H \"Authorization: Bearer vamo_sk_...\" \\\n  --data-urlencode \"q=senior rust engineers working on distributed databases\" \\\n  --data-urlencode \"depth=core\" \\\n  --data-urlencode \"limit=10\"\n```\n\n### Advanced filters\n\nEvery filter is optional and free — filters narrow the ranked pool, they never change the price. The GitHub-native filters (`lang`, `minCracked`, `orgs`, `subjects`, `techs`, `minStars`, `hideHighProfile`, `city`, …) apply to the whole indexed population. The professional filters resolved from the LinkedIn overlay (`titles`, `companySize`, `industries`, `peerCompanies`, `yoeMin`/`yoeMax`, `openToWork`, `experienceTier`, `state`) only match the linked-profile minority we hold, so they narrow the page sharply — reach for them when resolved professional detail matters more than reach. See each parameter's description in `openapi.json` for its exact coverage.\n\n```bash\ncurl -G https://api.vamotalent.ai/v1/developers/search \\\n  -H \"Authorization: Bearer vamo_sk_...\" \\\n  --data-urlencode \"q=distributed systems engineers\" \\\n  --data-urlencode \"lang=go,rust\" \\\n  --data-urlencode \"titles=staff engineer,principal engineer\" \\\n  --data-urlencode \"companySize=51-200\" \\\n  --data-urlencode \"yoeMin=8\" \\\n  --data-urlencode \"openToWork=true\" \\\n  --data-urlencode \"city=san francisco,new york\" \\\n  --data-urlencode \"hideHighProfile=true\" \\\n  --data-urlencode \"depth=enriched\"\n```\n"},"servers":[{"url":"https://api.vamotalent.ai","description":"Production"},{"url":"https://api-staging.vamotalent.ai","description":"Staging"}],"tags":[{"name":"search","description":"Find developers by what they have built. Plan a search from natural language, inspect the plan, then run it."},{"name":"developers","description":"Resolve identifiers (handles, GitHub or LinkedIn URLs, names, repos) to developer profiles, and enrich those profiles with facets. Enrichment is available inline for cached values and as a durable report for values that must be computed."},{"name":"deep-research","description":"Full-depth GitHub research on a named developer, persisted as a report the whole account can read. Jobs run in rounds and report per-subject outcomes, so a partial result is a normal answer rather than an error."}],"x-tagGroups":[{"name":"Search","tags":["search"]},{"name":"Developers","tags":["developers","deep-research"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"A session token (member) or an API key prefixed with vamo_sk_ (agent)."}},"schemas":{"DeepResearchNarrative":{"type":["object","null"],"properties":{"persona":{"type":"string","maxLength":640,"description":"The pitch: three to five sentences on what this developer is like to hire, written from this report and the engine’s read of their public work. A reading of a body of work, not a score: it asserts no employer, no title, no seniority and no location."},"sections":{"type":"object","properties":{"activity":{"type":["string","null"],"maxLength":640,"description":"How they work: their rhythm, and what having them on a team looks like."},"code":{"type":["string","null"],"maxLength":640,"description":"The work itself: what recurs in it, and what they build with it."},"social":{"type":["string","null"],"maxLength":640,"description":"How they work with other people, as their public work evidences it."}},"required":["activity","code","social"],"description":"The three supporting sections, each a paragraph. Each is nullable only while the narrative is still being completed: `narrativePending` says whether the missing ones are coming."}},"required":["persona","sections"],"description":"The written narrative of THIS report snapshot: the top summary (`persona`) and the activity, code and social paragraphs. Null when it has not been written yet, which is a normal state and never an error: it is generated off the hot path when the research job completes, a read that finds it missing or incomplete kicks the generation, and `narrativePending` is true until the complete prose is stored. Stored against the report row."},"DeepResearchReport":{"type":["object","null"],"properties":{"id":{"type":"string","description":"Identifier of this report."},"githubLogin":{"type":"string","description":"The GitHub handle the research was run on."},"status":{"type":"string","enum":["running","done","failed"],"description":"Whether the research finished. Only a `done` report carries a complete set of signals."},"failCode":{"type":["string","null"],"enum":["not_found","rate_limited","provider_error","timeout","engine_error"],"description":"Why the research failed, when it did. `engine_error` is our fault and is never billed. Null or absent on a report that succeeded."},"rawSignals":{"type":"object","additionalProperties":{"type":"number"},"description":"Signal name to the VALUE actually measured for this developer. Present whether or not the signal could be ranked, so this is the number to show when `pctSignals` has no entry for it. MEASURED is not the same claim as RANKED."},"pctSignals":{"type":"object","additionalProperties":{"type":"number"},"description":"Signal name to its percentile, 0..1, for the signals that could be ranked. A report MIXES ranking substrates, so one description never covers all of them: `signalPopulations[signal]` states which substrate each percentile here was ranked against. No percentile in this report is against a peer group matched on language, seniority, region or discipline — no such peer group exists; there is one measured population. A signal missing here is explained in `signalsExcluded`."},"composites":{"type":"object","properties":{"gemScore":{"type":"number","description":"The gem score: how far this developer’s demonstrated quality runs ahead of their visible reputation. Built from the percentiles in `pctSignals`, so it inherits their populations (`signalPopulations`) — mostly the developers Vamo has previously deep-researched, which grows, which makes this number not comparable across reports taken at different times."},"quality":{"type":"number","description":"The quality composite, built from the `qualityTerms` below."},"visibility":{"type":"number","description":"The visibility composite, built from the `visibilityTerms` below."},"reachable":{"type":"number","description":"The reachability composite."},"productionMaturity":{"type":"number","description":"The production-maturity cluster: how much this developer builds and RUNS production software — CI, instrumentation, releases, maintenance, tests — averaged across whichever of those signals they have. A cluster score, so no single thin signal drives it. Built from `pctSignals`, so it inherits their populations. Not a factor in `gemScore`."},"qualityTerms":{"type":"array","items":{"type":"object","properties":{"signal":{"type":"string","description":"The signal that contributed."},"weight":{"type":"number","description":"Its weight in the composite."},"pct":{"type":"number","description":"The developer’s percentile on that signal, 0 to 1. `signalPopulations[signal]` says which substrate it was ranked against, and a report mixes substrates, so read it before quoting this."}},"required":["signal","weight","pct"],"description":"One term of a composite score, so the composite can be decomposed instead of trusted blind."},"description":"The individual signals that fed `quality`, with their weights, so the composite can be decomposed rather than trusted blind."},"visibilityTerms":{"type":"array","items":{"type":"object","properties":{"signal":{"type":"string","description":"The signal that contributed."},"weight":{"type":"number","description":"Its weight in the composite."},"pct":{"type":"number","description":"The developer’s percentile on that signal, 0 to 1. `signalPopulations[signal]` says which substrate it was ranked against, and a report mixes substrates, so read it before quoting this."}},"required":["signal","weight","pct"],"description":"One term of a composite score, so the composite can be decomposed instead of trusted blind."},"description":"The individual signals that fed `visibility`, with their weights."},"productionMaturityTerms":{"type":"array","items":{"type":"object","properties":{"signal":{"type":"string","description":"The signal that contributed."},"weight":{"type":"number","description":"Its weight in the composite."},"pct":{"type":"number","description":"The developer’s percentile on that signal, 0 to 1. `signalPopulations[signal]` says which substrate it was ranked against, and a report mixes substrates, so read it before quoting this."}},"required":["signal","weight","pct"],"description":"One term of a composite score, so the composite can be decomposed instead of trusted blind."},"description":"The individual signals that fed `productionMaturity`, with their weights."}},"description":"Percentile-derived composite scores. EMPTY (`{}`) whenever the ranking population is below its floor, which is the normal case early on: the keys are absent together rather than zeroed, so absence means \"not ranked yet\", never \"scored zero\". Read `rawSignals` and say \"measured, not yet ranked\" instead of showing a bare blank."},"evidence":{"type":"array","items":{"type":"string"},"description":"Human-readable evidence lines the research produced."},"profile":{"type":["object","null"],"properties":{"login":{"type":"string","description":"The GitHub handle, as read live during the research."},"createdAt":{"type":"string","description":"When the GitHub account was created, as an ISO 8601 instant."},"followers":{"type":"number","description":"Follower count at research time."},"following":{"type":"number","description":"How many accounts they follow, at research time."},"organizations":{"type":"array","items":{"type":"string"},"description":"Public GitHub organisations they belong to. Private memberships are invisible, so an empty list is not evidence of none."},"socialAccounts":{"type":"array","items":{"type":"object","properties":{"provider":{"type":"string","description":"Which platform the link points at."},"url":{"type":"string","description":"The linked profile URL."}},"required":["provider","url"]},"description":"Social links the developer has published on their GitHub profile."}},"required":["login","createdAt","followers","following","organizations","socialAccounts"],"description":"The GitHub profile as read during the research. Open to extra keys: new fields arrive without a release here. Null when the profile could not be read."},"contributions":{"type":["object","null"],"properties":{"totalCommitContributions":{"type":"number","description":"Commits GitHub counted over the research window."},"totalPullRequestContributions":{"type":"number","description":"Pull requests opened over the window."},"totalPullRequestReviewContributions":{"type":"number","description":"Pull request reviews over the window."},"calendar":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","description":"The calendar day, `YYYY-MM-DD`."},"count":{"type":"number","description":"Contributions GitHub counted that day."},"weekday":{"type":"number","description":"Day of the week, 0 for Sunday through 6 for Saturday. Present so weekday and weekend activity can be told apart without re-deriving it."}},"required":["date","count","weekday"]},"description":"Daily contribution counts across the window."}},"required":["totalCommitContributions","totalPullRequestContributions","totalPullRequestReviewContributions","calendar"],"description":"Contribution activity, PUBLIC only: work in private repositories is invisible to GitHub’s counters, so low numbers are not evidence of low output. Null when it could not be read."},"repos":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"The repository name, without the owner."},"owner":{"type":"string","description":"The owning account’s login, which may be a person or an organisation."},"isFork":{"type":"boolean","description":"True when the repository is a fork. Forks are kept in the sample rather than dropped, so filter on this if you only want original work."},"primaryLanguage":{"type":["string","null"],"description":"GitHub’s primary language. Null when it reports none."},"languages":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"The language."},"size":{"type":"number","description":"Bytes of code GitHub attributes to it in this repository."}},"required":["name","size"]},"description":"Language breakdown by bytes of code, which is a proxy for effort and not a measure of skill."},"topics":{"type":"array","items":{"type":"string"},"description":"GitHub topics the owner tagged the repository with."},"stars":{"type":"number","description":"Stargazer count at research time."},"forks":{"type":"number","description":"Fork count at research time."},"pushedAt":{"type":"string","description":"When the repository was last pushed to, as an ISO 8601 instant."},"latestReleaseAt":{"type":["string","null"],"description":"When it last cut a release, as an ISO 8601 instant. Null when it has never released."},"contribution":{"type":["object","null"],"properties":{"relation":{"type":["string","null"],"enum":["owner","maintainer","core","reviewer","drive-by"],"description":"How the developer relates to this repository, first match wins: `owner` (their own repository), `maintainer` (merged other people’s PRs here, or merged two or more of their own PRs in a repository they do not own, which shows write access), `core` (ten or more of their authored PRs merged), `reviewer` (three or more reviews given with at most two authored PRs merged), `drive-by` (one or two authored PRs merged). Reviews alone never make someone a maintainer. Absent or null means unknown, never zero."},"commitsAuthored":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: commits the developer authored in this repository that GitHub credits to them (default branch, linked email), across the years the research read. Absent or null means unknown, never zero."},"authoredPrs":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: pull requests the developer opened in this repository, over about the trailing two years of public activity. Absent or null means unknown, never zero."},"authoredPrsMerged":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: of the PRs they opened here, how many were merged by anyone, including themselves, over about the trailing two years of public activity. Estimated from a sample when they opened more than the dive reads one by one. Absent or null means unknown, never zero."},"authoredPrsMergedByOthers":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: of their merged PRs here, how many someone other than the developer (and not a bot) merged, which is outside validation of the work, over about the trailing two years of public activity. Absent or null means unknown, never zero."},"selfMergedPrs":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: of their merged PRs here, how many the developer merged themselves, which shows write access rather than outside validation, over about the trailing two years of public activity. Absent or null means unknown, never zero."},"mergedForOthers":{"type":["number","null"],"minimum":0,"description":"MERGED-FOR-OTHERS work: other people’s PRs this developer merged here, read from the latest 50 merged PRs of each repository they own or hold write access to. A gatekeeping fact, never added to the authored counts. Absent or null means unknown, never zero."},"reviewsGiven":{"type":["number","null"],"minimum":0,"description":"REVIEW work: reviews the developer left on other people’s PRs here, over about the trailing two years of public activity. Neither authored nor merged work. Absent or null means unknown, never zero."},"filesTouchedMedian":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: the median number of files changed per merged PR the developer authored here, over about the trailing two years of public activity. Absent or null means unknown, never zero."},"firstMergedAt":{"type":["string","null"],"description":"AUTHORED work: when the earliest PR the developer authored here was merged, as an ISO 8601 instant. Absent or null means unknown, never zero."},"lastMergedAt":{"type":["string","null"],"description":"AUTHORED work: when the most recent PR the developer authored here was merged, as an ISO 8601 instant. Absent or null means unknown, never zero."},"prTitles":{"type":["array","null"],"items":{"type":"string"},"maxItems":8,"description":"AUTHORED work: titles of PRs the developer authored here, newest first, at most 8. Absent or null means unknown, never zero."}},"description":"What the developer did in this repository, AUTHORED work kept apart from MERGED-FOR-OTHERS work. Absent on reports produced before contribution depth existed, and absent means unknown, never zero."}},"required":["name","owner","isFork","primaryLanguage","languages","topics","stars","forks","pushedAt","latestReleaseAt"]},"description":"The repositories actually sampled by this research. A SAMPLE, not a complete list: `commitStats` says how much was sampled and how much was skipped."},"subjects":{"type":["array","null"],"items":{"type":"string"},"description":"WHAT-domain tags (fintech, mobile, devtools) read off the sampled repositories — owned AND contributed, manifests included — strength order. Null on reports produced before this field existed."},"technologies":{"type":["array","null"],"items":{"type":"string"},"description":"HOW-they-build tags (react, rust, kafka) read the same way as `subjects`, same vocabulary, computed alongside it but never blended in. Null on reports produced before this field existed."},"commitStats":{"type":"object","properties":{"sampleN":{"type":"number","description":"How many commits were examined."},"reposSampled":{"type":"number","description":"How many repositories were examined."},"reposSkipped":{"type":"number","description":"How many were skipped, typically for size. A high number here means the signals rest on a narrower base than the developer’s full output."}},"required":["sampleN","reposSampled","reposSkipped"],"description":"How much of the developer’s work this research actually looked at. Read it before treating the signals as comprehensive."},"familiesPresent":{"type":"array","items":{"type":"string"},"description":"Which signal families had enough data to contribute to this report."},"signalsGraded":{"type":"number","description":"How many signals were successfully percentile-ranked. The rest are explained in `signalsExcluded`."},"signalsExcluded":{"type":"object","additionalProperties":{"type":"string","enum":["no_family_data","insufficient_evidence","not_percentile","insufficient_cohort"]},"description":"Signal name to why it was not ranked, and the four reasons say genuinely different things. `insufficient_cohort` = the signal WAS measured (its value is in `rawSignals`) but the ranking population is too small to place it; do not render this as \"no evidence\". `insufficient_evidence` = this developer did not produce enough activity to measure it. `no_family_data` = its whole signal family was unavailable. `not_percentile` = the signal is not the kind of thing that gets ranked."},"signalPopulations":{"type":["object","null"],"additionalProperties":{"type":"object","properties":{"source":{"type":"string","enum":["benchmark_grid","dive_population","absolute"],"description":"Which substrate that percentile was ranked against. `benchmark_grid` = a published, versioned grid epoch. `dive_population` = the developers Vamo has deep-researched, which is deliberately biased toward ACTIVE developers. `absolute` = already a 0..1 measure, never ranked against anybody."}},"required":["source"]},"description":"Per graded signal, WHICH substrate its percentile was ranked against. THE field to read before quoting any percentile: a report mixes substrates, so one sentence never covers all of them, and a `dive_population` percentile is a coarser claim than a `benchmark_grid` one. Absent on reports produced before vamo-data started recording it."},"pointsSpent":{"type":"number","description":"GitHub API quota consumed by the whole round this report was part of, not by this developer alone. Divide by `roundLogins` for an average, and say that you did."},"requestCount":{"type":"number","description":"Upstream requests made by the whole round, shared by every developer in it. Divide by `roundLogins` for an average."},"roundLogins":{"type":"number","description":"How many developers shared the round. The divisor for `pointsSpent` and `requestCount`."},"startedAt":{"type":"string","description":"When the research started, as an ISO 8601 instant."},"finishedAt":{"type":"string","description":"When the research finished, as an ISO 8601 instant."},"contributionDepth":{"type":["object","null"],"properties":{"windowFrom":{"type":["string","null"],"description":"Start of the window the authored PR counts cover. Absent or null means unknown, never zero."},"windowTo":{"type":["string","null"],"description":"End of the window the authored PR counts cover. Absent or null means unknown, never zero."},"commitsAuthored":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: public commits GitHub credits to the developer across the years the research read. Absent or null means unknown, never zero."},"authoredPrs":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: pull requests the developer opened, over about the trailing two years of public activity. Absent or null means unknown, never zero."},"authoredPrsMerged":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: of those, how many were merged by anyone, over about the trailing two years of public activity. Absent or null means unknown, never zero."},"authoredPrsMergedExternal":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: merged PRs they authored in repositories they do not own, over about the trailing two years of public activity. Absent or null means unknown, never zero."},"authoredPrsMergedByOthers":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: merged PRs they authored that someone else (not a bot) merged, which is outside validation, over about the trailing two years of public activity. Absent or null means unknown, never zero."},"selfMergedPrs":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: merged PRs they authored and merged themselves, which shows write access rather than validation, over about the trailing two years of public activity. Absent or null means unknown, never zero."},"mergedForOthers":{"type":["number","null"],"minimum":0,"description":"MERGED-FOR-OTHERS work: other people’s PRs the developer merged, read from the latest 50 merged PRs of each repository they own or hold write access to. Never added to the authored counts. Absent or null means unknown, never zero."},"reviewsGiven":{"type":["number","null"],"minimum":0,"description":"REVIEW work: reviews they gave on other people’s PRs, over about the trailing two years of public activity. Absent or null means unknown, never zero."},"reviewsGivenExternal":{"type":["number","null"],"minimum":0,"description":"REVIEW work: reviews they gave in repositories they do not own, over about the trailing two years of public activity. Absent or null means unknown, never zero."},"externalRepos":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: distinct repositories they do not own with at least one merged PR they authored, over about the trailing two years of public activity. Absent or null means unknown, never zero."},"yearly":{"type":["array","null"],"items":{"type":"object","properties":{"year":{"type":"number","description":"The calendar year."},"commits":{"type":["number","null"],"minimum":0,"description":"AUTHORED commits GitHub credited to them that year. Absent or null means unknown, never zero."},"prs":{"type":["number","null"],"minimum":0,"description":"Pull requests they AUTHORED that year. Absent or null means unknown, never zero."},"reviews":{"type":["number","null"],"minimum":0,"description":"Reviews they gave on other people’s PRs that year. Absent or null means unknown, never zero."}},"required":["year"]},"description":"Public activity by calendar year, oldest first. Absent or null means unknown, never zero."},"prs":{"type":["array","null"],"items":{"type":"object","properties":{"repo":{"type":"string","description":"The repository as `owner/name`."},"number":{"type":"number","description":"The PR number in that repository."},"title":{"type":["string","null"],"description":"The PR title. Absent or null means unknown, never zero."},"merged":{"type":["boolean","null"],"description":"Whether the PR was merged. Absent or null means unknown, never zero."},"mergedAt":{"type":["string","null"],"description":"When it was merged, as an ISO 8601 instant. Null when unmerged. Absent or null means unknown, never zero."},"changedFiles":{"type":["number","null"],"minimum":0,"description":"How many files the PR touched. Absent or null means unknown, never zero."},"mergedBy":{"type":["string","null"],"enum":["self","other","bot"],"description":"`self` when the developer merged their own PR (write access, not outside validation), `other` when another person merged it, `bot` when automation did. Null when unmerged or unknown."},"reviewsReceived":{"type":["number","null"],"minimum":0,"description":"How many reviews other people left on this PR. Absent or null means unknown, never zero."}},"required":["repo","number"]},"maxItems":60,"description":"A sample of PRs the developer AUTHORED, at most 60, each saying who merged it. Absent or null means unknown, never zero."},"fileMix":{"type":["object","null"],"properties":{"samplePrs":{"type":["number","null"],"minimum":0,"description":"Merged PRs the developer AUTHORED whose file lists were read. Absent or null means unknown, never zero."},"reposSampled":{"type":["number","null"],"minimum":0,"description":"Repositories those PRs came from. Absent or null means unknown, never zero."},"filesTouched":{"type":["number","null"],"minimum":0,"description":"Changed files counted, after exclusions. Absent or null means unknown, never zero."},"filesExcluded":{"type":["number","null"],"minimum":0,"description":"Changed files dropped as vendored, generated or lockfiles. Absent or null means unknown, never zero."},"extensions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"In `extensions`: the lowercased final extension without the dot (`ts`, `rs`), a known bare file name (`dockerfile`, `makefile`), or `(none)` for other files with no extension. In `directories`: the lowercased top-level directory, or `/` for a file at the repository root."},"filesTouched":{"type":"number","minimum":0,"description":"Changed files under this key across the sampled authored PRs."},"prs":{"type":"number","minimum":0,"description":"Sampled authored PRs with at least one changed file under this key."}},"required":["key","filesTouched","prs"]},"maxItems":20,"description":"Files touched by extension, most files first, at most 20 keys, counted from the changed-file PATHS of merged PRs the developer AUTHORED (never line counts), with vendored, generated and lockfile paths excluded."},"directories":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"In `extensions`: the lowercased final extension without the dot (`ts`, `rs`), a known bare file name (`dockerfile`, `makefile`), or `(none)` for other files with no extension. In `directories`: the lowercased top-level directory, or `/` for a file at the repository root."},"filesTouched":{"type":"number","minimum":0,"description":"Changed files under this key across the sampled authored PRs."},"prs":{"type":"number","minimum":0,"description":"Sampled authored PRs with at least one changed file under this key."}},"required":["key","filesTouched","prs"]},"maxItems":20,"description":"Files touched by top-level directory, most files first, at most 20 keys, counted from the changed-file PATHS of merged PRs the developer AUTHORED (never line counts), with vendored, generated and lockfile paths excluded."}},"required":["extensions","directories"],"description":"Files touched by extension and by top-level directory in the developer’s own merged PRs. Absent when the report predates the file mix; null when the research could not read the file lists (unknown, never an empty mix)."}},"description":"Contribution depth beyond owned repositories: AUTHORED work and MERGED-FOR-OTHERS work, counted separately and never summed, from public work only. Absent on reports produced before this field existed, and absent means unknown, never zero."},"narrative":{"$ref":"#/components/schemas/DeepResearchNarrative"},"narrativePending":{"type":"boolean","description":"True while the narrative is missing, missing a section, or being rewritten (an older version is served meanwhile) AND is still being written: render the prose that is there, a placeholder for any missing piece, and read again shortly. False once all four current pieces are stored, and also false when they cannot be written (the retries for this report are spent), so a placeholder never waits forever."}},"required":["id","githubLogin","status","rawSignals","pctSignals","composites","evidence","profile","contributions","repos","commitStats","familiesPresent","signalsGraded","signalsExcluded","pointsSpent","requestCount","roundLogins","startedAt","finishedAt","narrative","narrativePending"],"description":"The full report body, identical to the recruiter deep-research report. Null unless ready."},"ProfileRepoWithTags":{"type":"object","properties":{"name":{"type":"string","maxLength":200,"description":"The repository name alone, without the owner (`linux`)."},"fullName":{"type":"string","maxLength":200,"description":"GitHub `owner/name`. This is the join key: an evidence repo and a profile repo describing the same repository carry the same `fullName`."},"description":{"type":["string","null"],"maxLength":5000,"description":"The repository's own GitHub description, verbatim. Null when it has none."},"language":{"type":["string","null"],"maxLength":200,"description":"GitHub's primary language for the repository. Null when GitHub reports none (an empty or docs-only repo); never inferred from the code."},"stars":{"type":"integer","minimum":0,"maximum":100000000,"description":"Stargazer count at the time this profile was snapshotted, not at request time."},"commits":{"type":"integer","minimum":0,"maximum":100000000,"description":"How many commits THIS developer authored to this repository over the trailing year. This is the difference between a project they wrote and a project they landed one drive-by fix in — a 385k-star repository with 4 of their commits is not their work. Absent when no commit signal was captured; 0 means none in the trailing year, which for older dormant work is not the same as none ever."},"owned":{"type":"boolean","description":"True when the repository sits under the developer's own account, false when it is someone else's (an organisation's or another person's) and they are a contributor to it. This is the difference between \"they built this\" and \"they committed to this\", and it is the ONLY honest basis for crediting a repository's stars to a person. Absent when no ownership signal was captured; treat absent as unknown, never as false."},"url":{"type":"string","maxLength":2048,"description":"The public github.com URL of the repository."},"subjects":{"type":"array","items":{"type":"string"},"description":"Subject/domain tags for this repository. Present only when `tags.repos` was resolved and this repo carried tags."},"technologies":{"type":"array","items":{"type":"string"},"description":"Technology tags for this repository. Present only when `tags.repos` was resolved and this repo carried tags."},"summary":{"type":"string","description":"A one-line, plain-English blurb on what this repository is, written for a non-technical reader. Present only when `ai.repo_summaries` was resolved and the model could describe this repo. The summaries are folded ONTO the repos you see here — there is no separate list — so what is described is exactly what is shown."},"themes":{"type":"array","items":{"type":"string"},"description":"A few short themes the AI drew from this repository. Present alongside `summary` when `ai.repo_summaries` was resolved."}},"required":["name","fullName","description","language","stars","url"],"description":"One public repository ATTRIBUTED to a developer: one they own, or one they have authored commits or pull requests into (so an org-owned project they maintain is theirs). Forks are excluded. Ordered most significant first. Read `owned` to tell a repository they built from one they contribute to, and `fullName` for who it actually belongs to. These are proof of work rather than an answer to \"why did this person match my query\" — that is `evidence.matchedRepos`."},"GardenSummary":{"type":"object","properties":{"from":{"type":"string","description":"First day of the garden window, `YYYY-MM-DD`, inclusive."},"to":{"type":"string","description":"Last day of the garden window, `YYYY-MM-DD`, inclusive."},"total":{"type":"integer","description":"Public contributions across the window."},"activeDays":{"type":"integer","description":"Days in the window with at least one contribution."},"activeWeeks":{"type":"integer","description":"Distinct weeks in the window with at least one contribution. Steady contributors score close to 52."},"last90Days":{"type":"integer","description":"Contributions in the 90 days ending on `to`."},"lastActiveDay":{"type":["string","null"],"description":"The most recent day with a contribution, `YYYY-MM-DD`. Null when the window is empty."},"byMonth":{"type":"object","additionalProperties":{"type":"integer"},"description":"Contributions per calendar month, `YYYY-MM` → count. Months with none are omitted."},"fetchedAt":{"type":"string","description":"When the underlying garden was read from GitHub, as an ISO 8601 instant."},"followers":{"type":["integer","null"],"description":"Current GitHub follower count, live. Null on a garden cached before live stats existed."},"totalStars":{"type":["integer","null"],"description":"Stars on repositories they OWN, live. Null on a garden cached before live stats existed."}},"required":["from","to","total","activeDays","activeWeeks","last90Days","lastActiveDay","byMonth","fetchedAt","followers","totalStars"],"description":"The contribution garden as a compact read (the default `garden=summary`): totals, active days and weeks, the last 90 days, per-month counts."},"PublicDetails":{"type":"object","properties":{"githubProfile":{"type":"object","properties":{"core":{"type":"object","additionalProperties":{},"description":"bio, currentRole, organization, university, languages, joinedAt, followers, following, totalStars."},"repos":{"type":"array","items":{"$ref":"#/components/schemas/ProfileRepoWithTags"},"description":"Top repositories (default 4), with `owned`/`commits` and, when resolved, `subjects`/`technologies` (`tags.repos`) and a plain-English `summary`/`themes` (`ai.repo_summaries`) folded on. The AI blurbs live HERE, on the repos shown, not in a separate list."}},"description":"The free GitHub profile: `githubProfile.core` (bio, org, languages, snapshot counts) and `githubProfile.repos`. Named for its source — everything here comes straight from GitHub."},"score":{"type":"object","properties":{"cracked":{"type":"object","additionalProperties":{},"description":"crackedScore, tier."}},"description":"The cracked score (`score.cracked`)."},"identity":{"type":"object","properties":{"linkedin":{"type":"object","additionalProperties":{},"description":"The resolved LinkedIn identity scalars (linkedin, headline, title, company, seniority, expertise, location)."},"experience":{"type":"array","items":{"type":"object","properties":{"title":{"type":["string","null"],"maxLength":200,"description":"Job title."},"company":{"type":["string","null"],"maxLength":200,"description":"Employer name."},"startDate":{"type":["string","null"],"maxLength":200,"description":"Start date exactly as the source rendered it. Free text, not normalised."},"endDate":{"type":["string","null"],"maxLength":200,"description":"End date, same unnormalised free-text form. Null on a current role."},"current":{"type":["boolean","null"],"description":"The source's own \"still there\" flag."}},"description":"One employment entry from the LinkedIn overlay, newest first. Unverified."},"description":"Employment history, newest first. Present only when non-empty."},"education":{"type":"array","items":{"type":"object","properties":{"school":{"type":["string","null"],"maxLength":200,"description":"Institution name."},"degree":{"type":["string","null"],"maxLength":200,"description":"Degree awarded."},"fieldOfStudy":{"type":["string","null"],"maxLength":200,"description":"Field of study."},"startDate":{"type":["string","null"],"maxLength":200,"description":"Start date as the source rendered it."},"endDate":{"type":["string","null"],"maxLength":200,"description":"End date as the source rendered it."}},"description":"One education entry from the LinkedIn overlay. Unverified."},"description":"Education history. Present only when non-empty."}},"description":"The resolved external identity (`enriched`): `identity.linkedin`, `identity.experience`, `identity.education`."},"contact":{"type":"object","properties":{"socials":{"type":"object","additionalProperties":{},"description":"github, linkedin social links."},"emails":{"type":"array","items":{"type":"string"},"description":"Every address we observe for this developer. Present only when we hold at least one, resolved via the emails route."},"location":{"type":["object","null"],"properties":{"raw":{"type":["string","null"],"maxLength":200,"description":"The location string exactly as the developer typed it on GitHub (\"SF / remote\")."},"city":{"type":["string","null"],"maxLength":200,"description":"City resolved from `raw` by geocoding. Null when `raw` was empty or unresolvable."},"state":{"type":["string","null"],"maxLength":200,"description":"The country subdivision (US state, province, region) as a full name, e.g. \"Ohio\". Present only from the clean LinkedIn overlay, for the developers we hold a match for. Absent otherwise: the GitHub geocoder does not reliably resolve it (so we do not surface its guess), and it is legitimately absent for city-states and metro-only profiles."},"country":{"type":["string","null"],"maxLength":200,"description":"Country resolved from `raw`. Null when `raw` was empty or unresolvable."},"source":{"type":"string","enum":["linkedin","github"],"description":"Where the resolved city/country came from: `linkedin` when our LinkedIn overlay supplied it (clean, self-reported on LinkedIn), `github` when it is geocoded from the GitHub `raw` string. Most developers have no LinkedIn match, so `github` is the common case and its city/country are often sparse. Absent on unresolved payloads."}},"required":["raw","city","country"],"description":"Where this developer is, resolved once and LinkedIn-preferred: `source` says whether the clean city/country came from their LinkedIn (`linkedin`) or from geocoding their GitHub location string (`github`). Present at `enriched`+ whenever `hasLocation` is true — the spine carries only the `hasLocation` flag. Note the GitHub geocode is rough (it often drops a country string into `city`); trust `source: \"linkedin\"` over `\"github\"`."}},"description":"Contact channels: `contact.socials` (enriched), `contact.location` (enriched), `contact.emails` (the emails route)."},"github":{"type":"object","properties":{"garden":{"type":"object","additionalProperties":{},"description":"The full contribution heatmap: every day’s count for the trailing year. Only with `garden=full`."},"gardenSummary":{"$ref":"#/components/schemas/GardenSummary"}},"description":"The live-GitHub block (`deep`): `github.gardenSummary` by default, or the full `github.garden` with `garden=full`."},"ai":{"type":"object","properties":{"person_summary":{"type":"object","properties":{"status":{"type":"string","enum":["ok","pending"]},"value":{"type":"object","additionalProperties":{}},"retryAfterMs":{"type":"number","description":"On `pending` only: milliseconds to wait before re-fetching this call. The value is compute-once/cached, so the retry returns `ok` fast once it lands."}},"required":["status"],"description":"A short, varied one-liner on who this developer is."},"repo_summaries":{"type":"object","properties":{"status":{"type":"string","enum":["ok","pending"]},"value":{"type":"object","additionalProperties":{}},"retryAfterMs":{"type":"number","description":"On `pending` only: milliseconds to wait before re-fetching this call. The value is compute-once/cached, so the retry returns `ok` fast once it lands."}},"required":["status"],"description":"Poll marker for the per-repo AI blurbs. The blurbs themselves fold onto `githubProfile.repos[].summary`/`.themes` (one-to-one with the repos shown), so this cell carries only `status`: `ok` means the blurbs are on the repos, `pending` (with `retryAfterMs`) means re-fetch. There is no `value` here."},"match_rationale":{"type":"object","properties":{"status":{"type":"string","enum":["ok","pending"]},"value":{"type":"object","additionalProperties":{}},"retryAfterMs":{"type":"number","description":"On `pending` only: milliseconds to wait before re-fetching this call. The value is compute-once/cached, so the retry returns `ok` fast once it lands."}},"required":["status"],"description":"Whether and why this developer matches the search query, judged against it. SEARCH ONLY (there is no query to judge against on an id lookup). `value` is `{ matched, reasons? }`: a real match is `{ matched: true, reasons: [\"Currently Staff Engineer at Stripe on payments\", \"Maintains a Go ISO-20022 library\", \"8 years shipping Go\"] }` — a list of short, positive, recruiter-facing bullets (repos, languages, LinkedIn role/company, organisation, location, tenure). A weak/non-match is `{ matched: false }` (no reasons — an honest verdict, not a manufactured one). Check `matched` before reading `reasons`."}},"description":"À-la-carte AI prose. `person_summary`/`repo_summaries` come from the `/developers/summaries` route or `facets=ai.person_summary,ai.repo_summaries` on any route. `match_rationale` comes from `facets=ai.match_rationale` on SEARCH — it is judged against your `q`. Compute is async: each member carries a `status` — `ok` or `pending` (with `retryAfterMs`: wait that long, then re-fetch this call once — the value is computed once and cached, so the retry returns fast). On `ok`, `person_summary` and `match_rationale` carry their `value` here; `repo_summaries` instead folds its blurbs onto `githubProfile.repos[]` and carries status only. Read status before value."}},"description":"Every detail about this developer beyond the identity spine, as a KEYED object nested by namespace. A namespace and a member appear only when resolved; absent details are omitted entirely. The set grows with depth: `core` fills `githubProfile.*` and `score.cracked`; `enriched` adds `identity.*`, `contact.socials` and `contact.location`; `deep` adds `github.garden`. À-la-carte: `tags.repos` folds onto `githubProfile.repos[]`, the emails route fills `contact.emails`."},"MatchRepo":{"type":"object","properties":{"fullName":{"type":"string","maxLength":160,"description":"GitHub `owner/name`. The join key onto `developer.repos[].fullName`, so you can match an evidence repo back to the profile repo it refers to."},"stars":{"type":"integer","minimum":0,"maximum":100000000,"description":"Stargazer count at retrieval time. 0 also means \"the source returned no count\", so do not read 0 as proof the repo is unstarred."},"language":{"type":["string","null"],"maxLength":200,"description":"GitHub’s primary language for the repository. Null when none was returned; never inferred from the code. Absent on pages produced before this field existed."},"role":{"type":["string","null"],"enum":["owner","contributor"],"description":"This person’s relationship to the repository, and it is deliberately conservative. `owner` means the repository sits under THEIR namespace. `contributor` means everything else, including the person who wrote most of the code in someone else’s or an organisation’s repository — a top committer on a company repo is a `contributor`, so do not read `contributor` as \"minor\" or `owner` as \"wrote it\". Null means the lane that produced this row genuinely cannot tell; absent means an older producer did not emit the field."}},"required":["fullName","stars"],"description":"One repository offered as evidence, with its own provenance. Read `via` for WHY it is here and `role` for the person’s relationship to it."},"DeveloperMatch":{"type":"object","properties":{"repos":{"type":"array","items":{"$ref":"#/components/schemas/MatchRepo"},"maxItems":12,"description":"The repositories that connect this developer to your query. Empty whenever `status` is `unattributed`."},"status":{"type":"string","enum":["attributed","unattributed"],"description":"Whether `repos` genuinely answers \"why did this person come back for my query\". `attributed` = it does. `unattributed` = the lane that answered cannot attribute repositories to the query, and `repos` is empty."}},"required":["repos","status"],"description":"Query attribution for this result: the matched repositories and whether the lane could attribute at all."},"DeveloperSpine":{"type":"object","properties":{"id":{"type":"string","maxLength":64,"description":"The stable GitHub numeric id for this developer. Immutable (unlike the login) — this is the handle to pass to every other endpoint."},"login":{"type":"string","maxLength":200,"description":"The GitHub handle as of the last snapshot. Display it, do not key on it: handles are renameable and reusable."},"name":{"type":["string","null"],"maxLength":200,"description":"Display name as the developer set it on GitHub. Null when they set none."},"avatarUrl":{"type":["string","null"],"maxLength":2048,"description":"GitHub avatar image URL. Null when absent."},"hasEmail":{"type":"boolean","description":"Whether we hold at least one email address for this developer. It says we have an address on file, not that the address works — we do not check deliverability. The addresses themselves are never returned by a search or a base profile read: this boolean is the free signal, and the paid `contact.emails` facet is the only way to get them. Use `hasEmail` on a search request to filter to developers we hold an address for, without paying."},"hasLinkedin":{"type":"boolean","description":"Whether we hold a LinkedIn match for this developer — i.e. whether `enriched` will return `identity.*` and `contact.socials` for them. Available on the same base row as `hasEmail`: read both to decide what depth is worth requesting."},"hasLocation":{"type":"boolean","description":"Whether we hold any resolved location for this developer (from LinkedIn or a geocoded GitHub string). A free presence flag alongside `hasEmail`/`hasLinkedin`. The resolved `location` OBJECT rides `details.contact.location` at `enriched` (like the LinkedIn URL), not on the spine. Filter on it with `requireLocation=true`."}},"required":["id","login","name","avatarUrl","hasEmail","hasLinkedin","hasLocation"],"description":"Who this developer is: the stable `id` to pass to every other endpoint, the handle, name and avatar to render them, and the free presence flags (`hasEmail`, `hasLinkedin`, `hasLocation`). Everything else — including the resolved `location` object — lives in `details`."},"PublicDeveloper":{"allOf":[{"$ref":"#/components/schemas/DeveloperSpine"},{"type":"object","properties":{"details":{"$ref":"#/components/schemas/PublicDetails"}},"required":["details"]}],"description":"One developer: the identity fields (`id`, `login`, `name`, `avatarUrl`, `hasEmail`, `hasLinkedin`, `hasLocation`) at the top level, plus the keyed `details` object resolved on this call (the resolved `location` object lives at `details.contact.location`, enriched). No fact is duplicated between the two."},"PublicSearchDeveloper":{"allOf":[{"$ref":"#/components/schemas/PublicDeveloper"},{"type":"object","properties":{"match":{"$ref":"#/components/schemas/DeveloperMatch"}},"required":["match"]}],"description":"One search result: the shared developer shape plus the query-attribution `match` block."},"DeepResearchItem":{"type":"object","properties":{"login":{"type":"string","description":"The subject reference this item researches: a GitHub handle for the `developers` subject, an `owner/name` for `repos`. The field name predates the second subject; `subjectRef` is the same value under its honest name."},"subjectRef":{"type":"string","description":"The subject reference, same value as `login`: a GitHub handle for `developers`, an `owner/name` for `repos`."},"status":{"type":"string","enum":["pending","running","done","failed"],"description":"Where this one subject stands. Items settle independently: partial success across a job is normal."},"failCode":{"type":["string","null"],"enum":["not_found","rate_limited","provider_error","timeout","abandoned","engine_error"],"description":"Machine-readable failure reason. Null while the item can still succeed or has succeeded. Branch on this, not on `failMessage`."},"failMessage":{"type":["string","null"],"description":"The failure explained in words you can show a user, including what to do about it. Null while the item can still succeed."},"source":{"type":["string","null"],"enum":["fresh","cache"],"description":"Whether the delivered answer was researched fresh or served from a recent previous run. The two are equivalent in content, but a cached answer must not be presented as fresh. Null until an answer lands."},"reportPath":{"type":["string","null"],"description":"The API path to read this subject’s report. Null until one exists."},"startedAt":{"type":["string","null"],"description":"When this item started, as an ISO 8601 instant. Null while queued."},"finishedAt":{"type":["string","null"],"description":"When this item settled, as an ISO 8601 instant. Null until it does."}},"required":["login","subjectRef","status","failCode","failMessage","source","reportPath","startedAt","finishedAt"],"description":"One subject within a deep-research job, and how it fared."},"DeepResearchJob":{"type":"object","properties":{"id":{"type":"string","description":"The job id. Poll it for progress."},"name":{"type":["string","null"],"description":"A short label generated from the developers the job was started with, for showing the job in a list. Null on jobs created before naming existed: fall back to the created time."},"subject":{"type":"string","enum":["developers","repos"],"description":"What kind of thing this job researches."},"status":{"type":"string","enum":["running","succeeded","partial","failed"],"description":"Where the job stands overall. Individual subjects settle independently; read `items` for the detail."},"createdAt":{"type":"string","description":"When the job was submitted, as an ISO 8601 instant."},"finishedAt":{"type":["string","null"],"description":"When the job reached a terminal state, as an ISO 8601 instant. Null while running."},"elapsedMs":{"type":"integer","minimum":0,"description":"Time so far while running, and total time once finished, in milliseconds. Computed server-side, so it does not depend on your clock."},"requestedCount":{"type":"integer","minimum":0,"description":"How many developers you asked for. Not all necessarily land a report: see `deliveredCount`."},"deliveredCount":{"type":"integer","minimum":0,"description":"How many developers actually landed a report. A developer whose research failed is not counted here."},"items":{"type":"array","items":{"$ref":"#/components/schemas/DeepResearchItem"},"description":"Per-developer state, including the reason for each one that did not land."}},"required":["id","name","subject","status","createdAt","finishedAt","elapsedMs","requestedCount","deliveredCount","items"],"description":"The job and its per-developer items."},"DeepResearchJobResponse":{"type":"object","properties":{"job":{"$ref":"#/components/schemas/DeepResearchJob"}},"required":["job"],"description":"One deep-research job."},"CreateDeepResearchJobRequest":{"oneOf":[{"type":"object","properties":{"subject":{"type":"string","enum":["developers"],"description":"Research developers. The field is a closed vocabulary so more subjects can be added without changing the job contract."},"logins":{"type":"array","items":{"type":"string","minLength":1,"maxLength":39,"pattern":"^[\\dA-Za-z-]+$"},"minItems":1,"maxItems":25,"description":"The GitHub handles to research, up to 25 per job. They are processed in rounds behind the job, not all at once."},"force":{"type":"boolean","description":"Re-research a subject even when a recent report exists. Costs the same either way, so use this only when you specifically need fresher data."},"githubConnectionId":{"type":"string","maxLength":16,"pattern":"^ghc_[0-9a-z]{12}$","description":"Ignored when calling with an API key (that path draws from your GitHub connection pool automatically). Only relevant for a signed-in dashboard member: the id of one of your linked GitHub connections (GET /v1/me/github), required in that case so the job runs on your own GitHub quota."}},"required":["subject","logins"]},{"type":"object","properties":{"subject":{"type":"string","enum":["repos"],"description":"Research repositories: who builds each one (recency-weighted contributors), who validates it (recent starrers plus where the repo’s star audience places), and identity facts on both."},"repos":{"type":"array","items":{"type":"string","minLength":1,"maxLength":140,"pattern":"^[\\dA-Za-z-]{1,39}\\/[\\w.-]{1,100}$"},"minItems":1,"maxItems":25,"description":"The repositories to research as `owner/name` references, up to 25 per job. They are processed in rounds behind the job, not all at once."},"force":{"type":"boolean","description":"Re-research a subject even when a recent report exists. Costs the same either way, so use this only when you specifically need fresher data."},"githubConnectionId":{"type":"string","maxLength":16,"pattern":"^ghc_[0-9a-z]{12}$","description":"Ignored when calling with an API key (that path draws from your GitHub connection pool automatically). Only relevant for a signed-in dashboard member: the id of one of your linked GitHub connections (GET /v1/me/github), required in that case so the job runs on your own GitHub quota."}},"required":["subject","repos"]}],"description":"A deep-research job to start. Returns immediately with a job to poll; billing settles per subject whose research actually lands."},"DeepResearchJobListResponse":{"type":"object","properties":{"jobs":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/DeepResearchJob"},{"description":"A deep-research job. Partial success is the normal outcome: the job says which subjects landed and, for each one that did not, exactly why."}]},"maxItems":200,"description":"The account’s deep-research jobs, newest first."}},"required":["jobs"],"description":"The account’s deep-research job history."},"DeepResearchRepoReport":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of this report."},"repoName":{"type":"string","description":"The `owner/name` the research was run on."},"status":{"type":"string","enum":["done","failed"],"description":"Whether the research finished."},"failCode":{"type":["string","null"],"enum":["not_found","rate_limited","provider_error","timeout"],"description":"Why the research failed, when it did. Null on a report that succeeded."},"meta":{"type":["object","null"],"additionalProperties":{},"description":"The repository header as read from GitHub at research time: description, topics, primary language, stars, forks, created/pushed instants, license, archived and fork flags."},"contributors":{"type":"array","items":{"type":"object","properties":{"depth":{"type":["object","null"],"properties":{"login":{"type":"string","description":"The contributor’s GitHub handle."},"authoredPrsMerged":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: merged PRs this contributor opened here, over the most recently updated merged PRs of this repository (up to 50) the research sampled. Absent or null means unknown, never zero."},"authoredPrsMergedByOthers":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: of those, how many another person (not a bot) merged, which is outside validation, over the most recently updated merged PRs of this repository (up to 50) the research sampled. Absent or null means unknown, never zero."},"selfMergedPrs":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: of those, how many the contributor merged themselves, which shows write access rather than validation, over the most recently updated merged PRs of this repository (up to 50) the research sampled. Absent or null means unknown, never zero."},"mergedForOthers":{"type":["number","null"],"minimum":0,"description":"MERGED-FOR-OTHERS work: other people’s PRs this contributor merged here, over the most recently updated merged PRs of this repository (up to 50) the research sampled. A gatekeeping fact, never added to the authored counts. Absent or null means unknown, never zero."},"reviewsGiven":{"type":["number","null"],"minimum":0,"description":"REVIEW work: reviews this contributor left on other people’s PRs here, over the most recently updated merged PRs of this repository (up to 50) the research sampled. A floor, since each PR’s reviews are read up to a cap. Absent or null means unknown, never zero."},"topExtensions":{"type":["array","null"],"items":{"type":"object","properties":{"extension":{"type":"string","description":"The lowercased final extension without the dot (`ts`, `rs`), a known bare file name (`dockerfile`), or `(none)`."},"filesTouched":{"type":"number","minimum":0,"description":"Changed files with this extension across the contributor’s own sampled merged PRs here, counted from paths (never line counts)."}},"required":["extension","filesTouched"]},"maxItems":5,"description":"The extensions this contributor’s own merged PRs here touch most, at most 5, vendored, generated and lockfile paths excluded. Absent or null means unknown, never zero."}},"required":["login"],"description":"What this contributor does here, read off the repository’s sampled merged PRs: the PRs they authored and how those were merged, the other people’s PRs they merged, the reviews they gave, and the file types their own PRs touch. Null when they do not appear in the sample; absent on reports produced before contributor depth existed. Absent or null means unknown, never zero."}}},"description":"Who actually builds this, recency-weighted: Push and merged-PR actors over the last year, scored so current maintainers outrank drive-by history. Each row carries the activity counts, first/last seen, whether they own the repo, `depth` (authored vs merged-for-others vs review work in this repository), and — where Vamo knows them — contact-shaped identity facts: name, title, LinkedIn URL, resolved city and country, raw location, company, cracked score 0-100 with its tier, gem score, seniority, years of experience, and `hasEmail` (the address itself is a paid facet)."},"earlyStarrers":{"type":["array","null"],"items":{"type":"object","additionalProperties":{}},"description":"The earliest recorded starrers — who was there before the crowd, oldest first, hydrated with the same identity facts. Dataset coverage starts 2023, so for older repos this is \"earliest recorded\", not \"earliest ever\". Absent on reports produced before it was recorded."},"starrers":{"type":"array","items":{"type":"object","additionalProperties":{}},"description":"A sample of the repo’s most recent starrers, hydrated with the same identity facts, so the CURRENT audience is readable person by person next to the `starPlacements` bands that summarise it."},"forkers":{"type":["array","null"],"items":{"type":"object","additionalProperties":{}},"description":"The repo’s most recent forkers, dated and hydrated with the same identity facts as `starrers`. Forks are the audience surface GitHub left open when it closed repo-side stargazer enumeration in 2026, so on a repo whose recent stars can no longer be read this list IS the current audience. Absent on reports produced before forkers were captured."},"starPlacements":{"type":["object","null"],"properties":{"audienceWeight":{"type":["object","null"],"properties":{"placement":{"type":"string","pattern":"^(Top (?:\\d{1,2}(?:\\.\\d{1,2})?|0\\.\\d{1,2})%|Bottom half)$","description":"Where this repository placed, already formatted for reading. Inside the top ten percent this carries real resolution (\"Top 7.9%\"); below it, a band (\"Top 25%\", \"Top 50%\", \"Bottom half\")."},"pct":{"type":"number","description":"The quantile it resolved to, 0..1. Ordering and debugging only — never rendered."}},"required":["placement","pct"],"description":"Where the authority-weighted weight of this repo’s audience places: stars counted in proportion to what the people giving them build and maintain themselves. A high band means practitioners with real work behind them are watching this."},"audienceShare":{"type":["object","null"],"properties":{"placement":{"type":"string","pattern":"^(Top (?:\\d{1,2}(?:\\.\\d{1,2})?|0\\.\\d{1,2})%|Bottom half)$","description":"Where this repository placed, already formatted for reading. Inside the top ten percent this carries real resolution (\"Top 7.9%\"); below it, a band (\"Top 25%\", \"Top 50%\", \"Bottom half\")."},"pct":{"type":"number","description":"The quantile it resolved to, 0..1. Ordering and debugging only — never rendered."}},"required":["placement","pct"],"description":"Where the builder SHARE of the recent audience places: how much of the recent attention comes from people who ship, rather than from passers-by. The hidden-gem read — a small project can place at the top here."},"authenticity":{"type":["string","null"],"enum":["organic","suspect"],"description":"A verdict on how the stars arrived: `organic` when the pattern looks like ordinary discovery, `suspect` when attention landed in bursts the way purchased or coordinated stars do. Null when it was not measured."},"epoch":{"type":"string","description":"The measurement day these placements were resolved against, as YYYY-MM-DD."}},"required":["audienceWeight","audienceShare","authenticity","epoch"],"description":"How this repo’s star audience places against the wider field of scored repositories, as formatted bands. This is the read for \"is this project respected by people who build, or just popular\": `audienceWeight` for the authority behind the audience, `audienceShare` for how much of it are builders rather than passers-by, and `authenticity` for whether the stars arrived the way real discovery arrives. Null when the repo is not scored, and absent on reports produced before placements were recorded — in both cases absence of a measurement, never a bad result."},"structuralMeasures":{"type":["object","null"],"properties":{"contributorDepth":{"type":["object","null"],"properties":{"status":{"type":"string","enum":["ok","unavailable"],"description":"`ok` when the merged-PR sample was read; `unavailable` when it could not be, which says nothing about the repository."},"source":{"type":["string","null"],"description":"Which lane produced the depth. Absent when unavailable."},"sampledPrs":{"type":["number","null"],"minimum":0,"description":"Merged PRs the sample read. Absent or null means unknown, never zero."},"windowFrom":{"type":["string","null"],"description":"The earliest merge in the sample, as an ISO 8601 instant. Absent or null means unknown, never zero."},"windowTo":{"type":["string","null"],"description":"The latest merge in the sample, as an ISO 8601 instant. Absent or null means unknown, never zero."},"unlisted":{"type":["array","null"],"items":{"type":"object","properties":{"login":{"type":"string","description":"The contributor’s GitHub handle."},"authoredPrsMerged":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: merged PRs this contributor opened here, over the most recently updated merged PRs of this repository (up to 50) the research sampled. Absent or null means unknown, never zero."},"authoredPrsMergedByOthers":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: of those, how many another person (not a bot) merged, which is outside validation, over the most recently updated merged PRs of this repository (up to 50) the research sampled. Absent or null means unknown, never zero."},"selfMergedPrs":{"type":["number","null"],"minimum":0,"description":"AUTHORED work: of those, how many the contributor merged themselves, which shows write access rather than validation, over the most recently updated merged PRs of this repository (up to 50) the research sampled. Absent or null means unknown, never zero."},"mergedForOthers":{"type":["number","null"],"minimum":0,"description":"MERGED-FOR-OTHERS work: other people’s PRs this contributor merged here, over the most recently updated merged PRs of this repository (up to 50) the research sampled. A gatekeeping fact, never added to the authored counts. Absent or null means unknown, never zero."},"reviewsGiven":{"type":["number","null"],"minimum":0,"description":"REVIEW work: reviews this contributor left on other people’s PRs here, over the most recently updated merged PRs of this repository (up to 50) the research sampled. A floor, since each PR’s reviews are read up to a cap. Absent or null means unknown, never zero."},"topExtensions":{"type":["array","null"],"items":{"type":"object","properties":{"extension":{"type":"string","description":"The lowercased final extension without the dot (`ts`, `rs`), a known bare file name (`dockerfile`), or `(none)`."},"filesTouched":{"type":"number","minimum":0,"description":"Changed files with this extension across the contributor’s own sampled merged PRs here, counted from paths (never line counts)."}},"required":["extension","filesTouched"]},"maxItems":5,"description":"The extensions this contributor’s own merged PRs here touch most, at most 5, vendored, generated and lockfile paths excluded. Absent or null means unknown, never zero."}},"required":["login"],"description":"What one contributor does in this repository, from its sampled merged PRs: the PRs they authored and how those were merged, the other people’s PRs they merged, the reviews they gave, and the file types their own PRs touch. AUTHORED and MERGED-FOR-OTHERS counts are never summed."},"maxItems":20,"description":"Depth for people absent from `contributors` (mergers and reviewers who rarely push), strongest first, at most 20. Absent or null means unknown, never zero."}},"required":["status"],"description":"Contributor depth for this repository: `status`, the merged-PR sample window, and `unlisted` (mergers and reviewers the ranked `contributors` list does not carry). Absent on reports produced before contributor depth existed."}},"description":"Work-distribution, succession, and momentum measurements over the FULL contributor set (not just the recency-weighted top slice above), anchored per-repo at that repo’s own last contribution: how many people carry half/80% of the work, the top-1/3/5 concentration shares, a Gini coefficient, quarter-over-quarter builder and activity momentum ratios, and contributor retention. Every flat field above measures HOW CONCENTRATED the building is and is blind to who does it; the nested `contributorQuality` block adds that axis, weighting the same work by each contributor’s cracked score (`eliteWorkMass`/`eliteWorkShare`, with `scoredContributors`/`scoredWorkShare` as their own coverage denominators, since an unscored contributor is outside the scored population rather than a weak one). It is nested because its POPULATION is different: the ranked top slice the `contributors` array carries, never the full set the flat fields aggregate, so the two are never averaged or compared. It rides here whenever contributors surfaced, including when the full-set measures did not. Null on reports computed before this measure existed."},"contributorGrowth":{"type":["object","null"],"additionalProperties":{},"description":"Distinct ACTIVE contributors per calendar month over the trailing year: `{ status: \"ok\", measure, source, months: [{ month, contributors }] }`. An activity trend, never a cumulative \"contributors ever\" total — it goes DOWN when a repo gets quieter, and `measure` names what the numbers are so a reader cannot relabel a decline as growth. `status: \"ok\"` with an empty `months` is a MEASUREMENT (the query ran, the repo had no in-window activity); `{ status: \"query_failed\" }` is not a measurement at all and is worth re-asking. Null means only that the report predates this measure, and a report written between it landing and the status wrapper carries the bare `{ measure, source, months }` object instead."},"audienceGrowth":{"type":["object","null"],"additionalProperties":{},"description":"The `forkers` and `starrers` lists re-aggregated into a month-by-month audience curve: ascending contiguous `months` of `{ month, forkers, scoredForkers, forkerEliteMass, starrers, scoredStarrers, starrerEliteMass }`, plus the `forkersTotal`/`forkersScored`/`starrersTotal`/`starrersScored` denominators behind them. Raw counts are the primary signal; the elite-mass fields are a partial-coverage overlay that weights each month’s audience by what those people build themselves, which is why each carries its own scored denominator rather than being averaged in. A month is `null` when NO source observed it (the frozen mirror and the live graph cover disjoint eras) and `0` only when a source did cover it and saw nothing, so a gap in the curve is never a quiet month. Null overall when neither list carried dated rows, and absent on reports produced before this was computed."},"commitActivity":{"type":["object","null"],"additionalProperties":{},"description":"Whether the CODE moves, where the audience curves say only who is watching: GitHub’s trailing-52-week commit rollup bucketed into `{ month, commits, weeks }` per calendar month. A verdict object rather than a bare trend, because the three ways there is no trend are three different facts. `{ status: \"ok\", months }` is measured, and a year of `commits: 0` there is a real finding about the repo. `{ status: \"not_computed\" }` means GitHub had not built the series when we asked (its stats endpoints answer a cold repo with an empty 202, and the ask itself warms it), so the next dive of the same repo likely gets it — never read it as a zero-commit year. `{ status: \"unavailable\" }` means the ask failed outright and says nothing about the repo. `weeks` is each month’s coverage denominator: a 52-week window opens and closes mid-month, so the first and last buckets hold fewer weeks and would otherwise read as a slump. Null when the report predates this measure; a report written between it landing and the verdict shape carries a bare ARRAY of months, which reads as `ok`."},"subjects":{"type":["array","null"],"items":{"type":"string"},"description":"WHAT-domain tags (fintech, mobile, devtools) read off this repo’s topics + description + manifest dependencies — never the README body, which has no cross-repo repetition to corroborate a loose match against for a single repo. Null on reports produced before this field existed."},"technologies":{"type":["array","null"],"items":{"type":"string"},"description":"HOW-it-builds tags (react, rust, kafka) read the same way as `subjects`, same vocabulary as a developer report’s `technologies`, computed alongside `subjects` but never blended in. Null on reports produced before this field existed."},"anchor":{"type":"string","description":"The dataset instant the contributor and starrer windows end at."},"contributionAnchor":{"type":["string","null"],"description":"The dataset instant the contribution (push/merged-PR) window ends at — later than `anchor`, since contribution data lags star data. Empty on reports computed before this measure existed."},"contributorsFound":{"type":"number","description":"How many contributors the report carries (the top slice by weight)."},"contributorsWindowTotal":{"type":"number","default":0,"description":"TOTAL distinct human contributors in the window. `contributors` is the top slice; this says what the cap hid. 0 on reports produced before it was recorded."},"starrersSampled":{"type":"number","description":"How many recent starrers were sampled."},"starrersWindowTotal":{"type":"number","default":0,"description":"TOTAL distinct starrers in the sample window. 0 on reports produced before it was recorded."},"forkersSampled":{"type":"number","default":0,"description":"How many recent forkers were sampled and hydrated into `forkers`. 0 on reports produced before forkers were captured."},"forkersWindowTotal":{"type":"number","default":0,"description":"TOTAL forks GitHub reports for the repo (its own `forkCount`), not just the sampled slice — the denominator that says whether `forkers` is the whole audience or the most recent face of it. 0 on reports produced before it was recorded."},"identitiesResolved":{"type":"number","description":"How many surfaced people resolved to a known identity in Vamo’s index — the denominator behind the hydrated facts."},"startedAt":{"type":"string","description":"When the research started, as an ISO 8601 instant."},"finishedAt":{"type":"string","description":"When the research finished, as an ISO 8601 instant."}},"required":["id","repoName","status","meta","contributors","starrers","anchor","contributorsFound","starrersSampled","identitiesResolved","startedAt","finishedAt"],"description":"A full deep-research report on one repository: the GitHub header, the recency-weighted contributors (current maintainers outrank drive-by history by construction), a recent-starrer sample, and `starPlacements` — where this repo’s star audience places against the wider field of scored repositories, as bands. Contributor depth rides on each contributor’s `depth` and on `structuralMeasures.contributorDepth`: who authors merged PRs, who merges other people’s PRs, who reviews, and which file types each contributor’s own PRs touch, with authored and merged-for-others work kept apart. It is present whenever the research ran with contributor depth; absent means the report predates it. People are hydrated with identity facts where Vamo’s index knows them — city, company, gem score, and whether an email is on file; the address itself stays a paid facet. Free to read: the job that produced it already paid, and the report is shared by everyone on the account."},"DeveloperSearchResponse":{"type":"object","properties":{"cursor":{"type":["string","null"],"maxLength":256,"pattern":"^[!-~]+$","description":"Opaque continuation token: pass it back as `cursor` for the next page. Null means the engine has no continuation left for this query. Do not parse it or construct one."},"cached":{"type":"boolean","description":"True when this page was served from a cached result set rather than a fresh engine run. A cached page can be missing the newer envelope fields and can carry `evidence.matchStatus: unattributed`. Caching does not change what you are charged: search is billed per developer returned either way."},"countStatus":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["exact"],"description":"You got exactly the number of results you asked for."}},"required":["kind"],"description":"The page delivered the requested count in full."},{"type":"object","properties":{"kind":{"type":"string","enum":["short"],"description":"The page returned fewer results than you asked for."},"requested":{"type":"integer","minimum":0,"maximum":250,"description":"The `limit` you sent."},"returned":{"type":"integer","minimum":0,"maximum":250,"description":"How many results this page actually carries. This is also what you were charged for: search bills per developer returned."},"shortfallReason":{"type":"string","enum":["filter_attrition","coverage","corpus","capability","call_budget","lane_window"],"description":"Why the page came up short, and each value is a deliberately different claim. `filter_attrition` = matches existed but your filters removed them from this page; page on. `coverage` = developers matched but could not be returned (no linked GitHub account). `corpus` = nobody else in the index matches — the only value that claims the data is exhausted. `capability` = the lane that could have answered was unavailable to this credential, so nothing is claimed about the data; retry with the cursor. `call_budget` = we stopped at our own per-request ceiling while the upstream cursor was still live; retry with the cursor. `lane_window` = a windowed lane ran out of window, which means this lane has no more to show and says NOTHING about whether the index holds more people. The windowed lanes are the repo fanout, the seed-repo gate, and a professional/geo search carrying free text, whose candidate pool is retrieved by the query before your filters are applied to it — on that last one, dropping `query` and keeping the levers reaches people the text window cannot."}},"required":["kind","requested","returned","shortfallReason"],"description":"The page returned fewer results than requested, with the reason declared."}],"description":"Whether you got the number of results you asked for, and if not, why. Never padded and never silently short."},"results":{"type":"array","items":{"$ref":"#/components/schemas/PublicSearchDeveloper"},"maxItems":250,"description":"The developers on this page, best-match first. The order IS the relevance ranking. Each carries a `match` block attributing the query to their repositories."}},"required":["cursor","cached","results"],"description":"One page of developers, the cursor to continue on, and `countStatus`: whether the page came up short of the `limit` you asked for, and why."},"PublicDeveloperList":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/PublicDeveloper"},"maxItems":250,"description":"The developers we hold data for, in the same shape a search result carries. Ids we hold nothing for are omitted rather than returned empty — and are not billed."}},"required":["results"],"description":"Developers in the shared public shape."},"PublicDeveloperEmailsList":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/PublicDeveloper"},"maxItems":250,"description":"The developers we hold data for; any addresses we observe land under `details.contact.emails`. Ids we hold nothing for are omitted."}},"required":["results"],"description":"Observed email addresses, on the shared developer shape (under `details.contact.emails`)."},"PublicSimilarDeveloper":{"allOf":[{"$ref":"#/components/schemas/PublicDeveloper"},{"type":"object","properties":{"whySimilar":{"type":"string","description":"One or two matter-of-fact sentences on how this candidate relates to the seed — shared repositories, a graph bridge, mutual follows. Deterministic (templated from the relatedness evidence, no model), so it reads the same every time. Absent when the graph surfaced the candidate with no describable overlap."}}}],"description":"A find-similar candidate: the shared developer shape plus the why-similar explanation."},"PublicSimilarList":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/PublicSimilarDeveloper"},"maxItems":50,"description":"The related developers, in graph order, each with its deterministic why-similar line."}},"required":["results"],"description":"Find-similar candidates in the shared public shape, each with a why-similar line."},"FitRankResult":{"type":"object","properties":{"login":{"type":"string","maxLength":39,"description":"The GitHub login that was scored."},"developerId":{"type":"string","maxLength":64,"description":"The canonical developerId the login resolved to."},"fit":{"type":"number","description":"How well they fit the role, 0 (off-topic/toy) to 2 (strong direct fit). 0 when they could not be scored."},"gettable":{"type":"number","description":"How realistically they could be recruited, 0 to 1."},"bridgeable":{"type":"number","description":"How readily they could bridge into the role, 0 to 1."},"confidence":{"type":"number","description":"The model’s confidence in the fit score, 0 to 1."},"bridge":{"type":"string","maxLength":5000,"description":"A short reason they can bridge into the role, or empty when the model gave none."},"scored":{"type":"boolean","description":"True when the model scored them; false when the per-candidate scoring failed (the row sits at the bottom and is not billed)."},"prescore":{"type":"number","description":"A deterministic evidence score, no model involved: the sum of the substance of their three strongest repositories (pull requests they authored that were merged, or commits they authored, scaled by reviews, depth, relation and stars), read from their pull-request record. Absent when that record was not read (absent is unknown, not 0). It only breaks ties after confidence. A relative score, not a unit."}},"required":["login","developerId","fit","gettable","bridgeable","confidence","bridge","scored"],"description":"One ranked candidate."},"FitRankDropped":{"type":"object","properties":{"login":{"type":"string","maxLength":39,"description":"The GitHub login that was left out."},"developerId":{"type":"string","maxLength":64,"description":"The canonical developerId the login resolved to."},"reason":{"type":"string","enum":["celebrity"],"description":"Why it was left out. `celebrity`: too prominent to be a realistic recruit (very large following or a flagship repo). Never scored, never billed."}},"required":["login","developerId","reason"],"description":"A resolved candidate left out of the ranking, with the reason."},"FitRankResponse":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/FitRankResult"},"maxItems":50,"description":"Every resolved, non-dropped candidate, best fit first; ties go to the more recruitable (higher gettable), then to confidence, then to `prescore`. Low gettability is ranked, not hidden, so filter on `gettable` yourself. A candidate that could not be scored sits at the bottom with `scored:false`."},"misses":{"type":"array","items":{"type":"string","maxLength":39},"maxItems":50,"description":"Logins that did not resolve to a developer."},"dropped":{"type":"array","items":{"$ref":"#/components/schemas/FitRankDropped"},"maxItems":50,"description":"Resolved candidates left out of the ranking, each with its reason. Every input login lands in exactly one of `results`, `misses` or `dropped`."},"scoredCount":{"type":"number","description":"How many candidates were successfully scored. This is what the call is billed on (2 credits each)."}},"required":["results","misses","dropped","scoredCount"],"description":"Ranked candidates, the logins that did not resolve, and the ones left out with a reason."},"FitRankRequest":{"type":"object","properties":{"logins":{"type":"array","items":{"type":"string","minLength":1,"maxLength":39,"pattern":"^[\\dA-Za-z-]+$"},"minItems":1,"maxItems":50,"description":"GitHub logins to score, 1 to 50. Each is resolved to a developer; an unresolvable login comes back in `misses`."},"role":{"type":"string","maxLength":20000,"description":"The role or full job description to score fit against, up to 20,000 characters. Optional: with no role, fit is scored on intrinsic build quality instead."},"company":{"type":"string","maxLength":200,"description":"The hiring company, passed to the model as context for the role."}},"required":["logins"],"description":"A set of GitHub logins to fit-rank against a role."},"ApiError":{"type":"object","description":"The body every 4xx response carries.","required":["code","message","status"],"properties":{"code":{"type":"string","enum":["bad_request","unauthorized","signature_required","payment_required","forbidden","not_found","conflict","gone","payload_too_large","unprocessable_entity","too_many_requests","internal_error","not_implemented","billing_unavailable","not_contactable","mailbox_link_unavailable","mailbox_required","mail_engine_unavailable","webhook_publisher_unavailable","database_unavailable","client_error","build_failed"],"description":"Stable machine-readable error code. Branch on this, never on the numeric status."},"message":{"type":"string","description":"Human-readable explanation of the refusal."},"status":{"type":"integer","description":"The HTTP status code, repeated in the body."},"remedy":{"type":"object","description":"A self-serve path forward, when one exists (a 402 points at how to restore access).","required":["kind","url"],"properties":{"kind":{"type":"string","enum":["topup","connect_mailbox"],"description":"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."},"url":{"type":"string","description":"Where to go to clear the condition: an API path, or a web app page when only a person can."}}}},"additionalProperties":true}},"parameters":{}},"paths":{"/v1/deep-research/jobs":{"post":{"summary":"Start a deep-research job on up to 25 subjects (developers or repositories)","description":"Runs full-depth research on each subject and persists a report the whole account can read afterwards. `subject: \"developers\"` researches GitHub handles; `subject: \"repos\"` researches `owner/name` repositories — who builds each one (recency-weighted contributors), who validates it (recent starrers plus where the repo’s star audience places, weighing every starrer by the authority of what they themselves build), and identity facts on both. Returns immediately with a job you poll; rounds of five developers run behind it. A developer served from a recent previous research is equivalent in content to a fresh one. Partial success is normal: the job tells you which subjects landed and, for each one that did not, exactly why.\n\n---\n**Access** Authenticated (`research:deep`) · **Rate limit** 6 / minute per account · **Quota** `deep_research`","tags":["deep-research"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeepResearchJobRequest"},"example":{"subject":"developers","logins":["gaearon"]}}}},"responses":{"202":{"description":"The job, with every subject pending","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeepResearchJobResponse"}}}},"401":{"description":"No or invalid credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Plan lacks search:deep, or insufficient balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Missing search:deep (role)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Submit rate limit or the deep-research quota is exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"x-vamo":{"access":"authenticated","audience":"search","rateLimit":{"kind":"fixed","limit":6,"window":"minute","scope":"account","perSeconds":60},"entitlement":"research:deep","quota":"deep_research"},"x-audience":["search","agent"],"operationId":"postDeepResearchJobs"},"get":{"summary":"List the account’s deep-research jobs","description":"The deep-research history for the account, newest first, each with its subjects. Self-scoped and free.\n\n---\n**Access** Authenticated (self) · **Rate limit** 120 / minute per account","tags":["deep-research"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The job history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeepResearchJobListResponse"}}}},"401":{"description":"No or invalid credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"A rate limit or a usage quota is exhausted. Back off and retry; the `x-quota-*` response headers report the remaining allowance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"x-vamo":{"access":"self","audience":"search","rateLimit":{"kind":"fixed","limit":120,"window":"minute","scope":"account","perSeconds":60}},"x-audience":["search","agent"],"operationId":"getDeepResearchJobs"}},"/v1/deep-research/jobs/{id}":{"get":{"summary":"Poll a deep-research job","description":"The job, its elapsed time, and every subject with its current stage. Polling also DRIVES the job: each read advances the next round and stops any subject whose runner died, so a job can never sit in a stage with nothing happening and no explanation. Self-scoped and free.\n\n---\n**Access** Authenticated (self) · **Rate limit** 120 / minute per account","tags":["deep-research"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","maxLength":16,"pattern":"^drj_[0-9a-z]{12}$"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The job","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeepResearchJobResponse"}}}},"401":{"description":"No or invalid credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such deep-research job in this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"A rate limit or a usage quota is exhausted. Back off and retry; the `x-quota-*` response headers report the remaining allowance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"x-vamo":{"access":"self","audience":"search","rateLimit":{"kind":"fixed","limit":120,"window":"minute","scope":"account","perSeconds":60}},"x-audience":["search","agent"],"operationId":"getDeepResearchJobsById"}},"/v1/deep-research/reports/developers/{login}":{"get":{"summary":"Read a persisted deep-research report for a developer","description":"The full research report a completed job produced: `pctSignals` maps each graded signal to its percentile, `signalsExcluded` names every signal that could not be graded and why, plus the composites, the contribution history, and the repositories sampled. Readable only for a developer this account has already researched, and free to read from then on — the job that produced it already paid, the report is persisted, and everyone on the account shares it. A developer the account has not researched is a 404, whether or not anyone else has. `signalPopulations` says, per graded signal, WHICH substrate its percentile was ranked against: a `dive_population` ranking is a coarser claim than a `benchmark_grid` one, and an `absolute` signal was never ranked against anybody. None of these are peer groups matched on language, seniority or region — there is one global measured population.\n\n---\n**Access** Authenticated (`search:deep`) · **Rate limit** 120 / minute per account","tags":["deep-research"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":39,"pattern":"^[\\dA-Za-z-]+$"},"required":true,"name":"login","in":"path"}],"responses":{"200":{"description":"The persisted report","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DeepResearchReport"},{"type":"object","description":"A full deep-research report on one developer. Read `rawSignals` for what was MEASURED and `pctSignals` for what could be RANKED — they are different claims, and `signalsExcluded` says why a measured signal is missing from the ranking. Percentiles do not share one substrate: `signalPopulations` names the substrate behind EACH graded signal, so read it per signal rather than describing the report with one phrase. Nothing here is a percentile against GitHub as a whole, and nothing here is against a peer group matched on language, seniority, region or discipline — Vamo ranks against a single global measured population, and no matched peer group exists. Free to read: the job that produced it already paid, and the report is shared by everyone on the account."}]}}}},"401":{"description":"No or invalid credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Plan lacks search:deep","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Missing search:deep (role)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"This account has not researched this developer (or nobody has)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"A rate limit or a usage quota is exhausted. Back off and retry; the `x-quota-*` response headers report the remaining allowance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"x-vamo":{"access":"authenticated","audience":"search","rateLimit":{"kind":"fixed","limit":120,"window":"minute","scope":"account","perSeconds":60},"entitlement":"search:deep"},"x-audience":["search","agent"],"operationId":"getDeepResearchReportsDevelopersByLogin"}},"/v1/deep-research/reports/repos/{owner}/{name}":{"get":{"summary":"Read a persisted deep-research report for a repository","description":"The full research report a completed `repos` job produced: contributors weighted toward recent work, a recent-starrer sample, identity facts on every surfaced person the index knows, and `starPlacements` — where this repo’s star audience places, as bands, so you can tell a project practitioners respect from one that is merely popular. Readable only for a repository this account has already researched, and free to read from then on. A repository the account has not researched is a 404, whether or not anyone else has.\n\n---\n**Access** Authenticated (`search:deep`) · **Rate limit** 120 / minute per account","tags":["deep-research"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":39,"pattern":"^[\\dA-Za-z-]+$"},"required":true,"name":"owner","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[\\w.-]+$"},"required":true,"name":"name","in":"path"}],"responses":{"200":{"description":"The persisted report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeepResearchRepoReport"}}}},"401":{"description":"No or invalid credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Plan lacks search:deep","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Missing search:deep (role)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"This account has not researched this repository (or nobody has)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"A rate limit or a usage quota is exhausted. Back off and retry; the `x-quota-*` response headers report the remaining allowance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"x-vamo":{"access":"authenticated","audience":"search","rateLimit":{"kind":"fixed","limit":120,"window":"minute","scope":"account","perSeconds":60},"entitlement":"search:deep"},"x-audience":["search","agent"],"operationId":"getDeepResearchReportsReposByOwnerByName"}},"/v1/developers/search":{"get":{"tags":["search"],"summary":"Search developers","description":"Search GitHub developers semantically and get one page back, enriched to the depth you ask for.\n\n**Reach filters.** `requireEmail`, `requireLinkedin` and `requireLocation` all **default to `false`** — search stays open by default so a plain query returns the full ranked pool and fills your `limit`. Opt in (`requireEmail=true`) only when you want to narrow to people we can reach. All three only FILTER; none returns an address.\n\n**Reading a result.** Each result is a flat identity object (`id`, `login`, `name`, `avatarUrl`, `hasEmail`, `hasLinkedin`, `hasLocation`) plus a keyed `details` object nested by namespace — `details.githubProfile.core`, `details.githubProfile.repos`, `details.score.cracked`, `details.identity.linkedin` / `details.identity.experience` / `details.identity.education`, `details.contact.socials` / `details.contact.location` / `details.contact.emails`, `details.github.garden`. The resolved `location` object rides `details.contact.location` at `enriched`; the spine carries only the free `hasLocation` flag. A namespace and its members appear only when resolved; absent details are omitted entirely. Per-repo subject/technology tags fold onto `details.githubProfile.repos[]` when `tags.repos` was resolved. Nothing is duplicated between the identity fields and the details. Rows arrive best-match first: **the order is the ranking**, there is no per-row score to read. `match.repos` is why this person matched; `match.status: \"unattributed\"` means the lane that answered cannot attribute, not that the match is weak. `match` is search-only — the id-based routes carry no query and omit it.\n\n**Short pages.** A page can come back shorter than `limit`, and `countStatus` is how you read it. `{\"kind\":\"exact\"}` means you got the full ask. `{\"kind\":\"short\"}` carries `requested`, `returned` and a `shortfallReason`, and only `corpus` claims the index is exhausted: `filter_attrition`, `call_budget`, `coverage` and `lane_window` all mean more may exist, so ask again with the `cursor`. A page served from cache can omit `countStatus` entirely.\n\n---\n**Access** Authenticated (`search:read`) · **Rate limit** 30 / minute per account","parameters":[{"schema":{"type":"string","maxLength":500,"description":"Free-text description of who you are looking for, matched semantically. This carries the intent; every other parameter narrows it. Either `q` or at least one narrowing parameter is required."},"required":false,"description":"Free-text description of who you are looking for, matched semantically. This carries the intent; every other parameter narrows it. Either `q` or at least one narrowing parameter is required.","name":"q","in":"query"},{"schema":{"type":"string","enum":["core","enriched","deep"],"default":"core","description":"How much data comes back per developer. `core`: the profile (login, name, company, followers, top repositories with descriptions and languages), the query `match` block (search only) and the cracked score. `enriched`: all of core, plus the resolved LinkedIn identity, social links and the resolved `location` object. `deep`: all of enriched, plus the contribution garden — the full contribution heatmap, by far the largest block on the wire, which is why it is its own tier: stay on core or enriched when you do not need it. Depth is how far OUT a tier reaches (core = what we already hold on GitHub, enriched = external identity, deep = live GitHub). Qualitative extras are NOT depth tiers — the AI-written summaries and the per-repo subject/technology tags are separate à-la-carte facets, resolved once and cross-account cached."},"required":false,"description":"How much data comes back per developer. `core`: the profile (login, name, company, followers, top repositories with descriptions and languages), the query `match` block (search only) and the cracked score. `enriched`: all of core, plus the resolved LinkedIn identity, social links and the resolved `location` object. `deep`: all of enriched, plus the contribution garden — the full contribution heatmap, by far the largest block on the wire, which is why it is its own tier: stay on core or enriched when you do not need it. Depth is how far OUT a tier reaches (core = what we already hold on GitHub, enriched = external identity, deep = live GitHub). Qualitative extras are NOT depth tiers — the AI-written summaries and the per-repo subject/technology tags are separate à-la-carte facets, resolved once and cross-account cached.","name":"depth","in":"query"},{"schema":{"type":"string","maxLength":605,"description":"À-la-carte facet keys to resolve ON TOP OF the depth tier, comma-separated, at most 5 — e.g. `tags.repos` to get the deterministic per-repo subject/technology tags folded onto `details.githubProfile.repos[]`. An unknown or non-public key is a 400; a facet already inside the chosen tier is a no-op."},"required":false,"description":"À-la-carte facet keys to resolve ON TOP OF the depth tier, comma-separated, at most 5 — e.g. `tags.repos` to get the deterministic per-repo subject/technology tags folded onto `details.githubProfile.repos[]`. An unknown or non-public key is a 400; a facet already inside the chosen tier is a no-op.","name":"facets","in":"query"},{"schema":{"type":"string","enum":["full","summary"],"description":"Which shape the contribution garden comes back in. `summary` (the default) is a compact `gardenSummary`: totals, active days and weeks, the last 90 days, the last active day and per-month counts, with `garden` null. `full` is the whole `garden`: every day’s count for the trailing year, for drawing a heatmap.","example":"summary"},"required":false,"name":"garden","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":250,"default":25,"description":"Developers per page, 1-250 (default 25). A large page's tail is less finely ranked, so ask for what you will use."},"required":false,"description":"Developers per page, 1-250 (default 25). A large page's tail is less finely ranked, so ask for what you will use.","name":"limit","in":"query"},{"schema":{"type":"string","maxLength":256,"description":"Opaque cursor from a previous response. Lane-scoped: do not construct, parse or reuse across different queries."},"required":false,"description":"Opaque cursor from a previous response. Lane-scoped: do not construct, parse or reuse across different queries.","name":"cursor","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Programming languages a developer must have demonstrated, e.g. `go,rust`. Filters on EVIDENCE, not on absence: a developer we hold no language data for is not excluded by this parameter."},"required":false,"description":"Programming languages a developer must have demonstrated, e.g. `go,rust`. Filters on EVIDENCE, not on absence: a developer we hold no language data for is not excluded by this parameter.","name":"lang","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Demonstrated abilities, matched semantically against what the person has actually built. Use `lang` when something is genuinely mandatory."},"required":false,"description":"Demonstrated abilities, matched semantically against what the person has actually built. Use `lang` when something is genuinely mandatory.","name":"skills","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Countries to restrict to, e.g. `united states,canada`."},"required":false,"description":"Countries to restrict to, e.g. `united states,canada`.","name":"country","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Cities to restrict to, matched against our geocoding of the self-reported location, e.g. `san francisco,berlin`. Like `country`, it filters on EVIDENCE: a developer we hold no location for is not excluded."},"required":false,"description":"Cities to restrict to, matched against our geocoding of the self-reported location, e.g. `san francisco,berlin`. Like `country`, it filters on EVIDENCE: a developer we hold no location for is not excluded.","name":"city","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"States or regions to restrict to, e.g. `california,ontario`. Subdivisions resolve mostly from the LinkedIn overlay — the GitHub geocoder rarely returns a reliable state — so this restricts to the linked-profile minority we hold, expect small pages, like `requireLinkedin`."},"required":false,"description":"States or regions to restrict to, e.g. `california,ontario`. Subdivisions resolve mostly from the LinkedIn overlay — the GitHub geocoder rarely returns a reliable state — so this restricts to the linked-profile minority we hold, expect small pages, like `requireLinkedin`.","name":"state","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Companies the person works at NOW."},"required":false,"description":"Companies the person works at NOW.","name":"company","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Companies to EXCLUDE — drop developers who currently work at any of these, e.g. exclude your own competitors. A real push-down (not a post-filter)."},"required":false,"description":"Companies to EXCLUDE — drop developers who currently work at any of these, e.g. exclude your own competitors. A real push-down (not a post-filter).","name":"excludeCurrentCompanies","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Companies the person used to work at. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `requireLinkedin`. It matches the FULL employment history, so a row that matched `google` can still show a different employer in `details.githubProfile.core.organization` (that field carries their GitHub-listed current company). Pass `depth=enriched` to see the matched employer in `details.identity.experience`."},"required":false,"description":"Companies the person used to work at. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `requireLinkedin`. It matches the FULL employment history, so a row that matched `google` can still show a different employer in `details.githubProfile.core.organization` (that field carries their GitHub-listed current company). Pass `depth=enriched` to see the matched employer in `details.identity.experience`.","name":"pastCompanies","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Schools/universities the person attended, e.g. `stanford university,mit`. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `requireLinkedin`. It matches the FULL education history, so a row that matched `mit` can still show a different school in `details.githubProfile.core.university` (that field carries only their most recent institution). Pass `depth=enriched` to see the matched school in `details.identity.education`."},"required":false,"description":"Schools/universities the person attended, e.g. `stanford university,mit`. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `requireLinkedin`. It matches the FULL education history, so a row that matched `mit` can still show a different school in `details.githubProfile.core.university` (that field carries only their most recent institution). Pass `depth=enriched` to see the matched school in `details.identity.education`.","name":"schools","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Job titles to aim at, e.g. `staff engineer,engineering manager`. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `pastCompanies`/`requireLinkedin`."},"required":false,"description":"Job titles to aim at, e.g. `staff engineer,engineering manager`. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `pastCompanies`/`requireLinkedin`.","name":"titles","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Industries the person works in, e.g. `fintech,healthcare`. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `requireLinkedin`."},"required":false,"description":"Industries the person works in, e.g. `fintech,healthcare`. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `requireLinkedin`.","name":"industries","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Companies to treat as reference points for \"companies like these\", rather than as an allowlist in themselves. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `requireLinkedin`."},"required":false,"description":"Companies to treat as reference points for \"companies like these\", rather than as an allowlist in themselves. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `requireLinkedin`.","name":"peerCompanies","in":"query"},{"schema":{"type":"string","enum":["1-50","51-200","201-2000","2000+"],"description":"Size band of the person’s CURRENT employer: `1-50`, `51-200`, `201-2000` or `2000+`. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `requireLinkedin`."},"required":false,"description":"Size band of the person’s CURRENT employer: `1-50`, `51-200`, `201-2000` or `2000+`. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `requireLinkedin`.","name":"companySize","in":"query"},{"schema":{"type":"string","enum":["early","upToSenior","senior","all"],"description":"A coarse experience band to aim at: `early`, `upToSenior`, `senior` or `all`. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `requireLinkedin`."},"required":false,"description":"A coarse experience band to aim at: `early`, `upToSenior`, `senior` or `all`. Resolved from the LinkedIn overlay, so it restricts to the linked-profile minority we hold — expect small pages, like `requireLinkedin`.","name":"experienceTier","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Minimum years of experience. Resolved from the LinkedIn total-experience overlay column, so a profile with no overlay value falls outside the band — it restricts to the linked-profile minority we hold. Pairs with `yoeMax`."},"required":false,"description":"Minimum years of experience. Resolved from the LinkedIn total-experience overlay column, so a profile with no overlay value falls outside the band — it restricts to the linked-profile minority we hold. Pairs with `yoeMax`.","name":"yoeMin","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Maximum years of experience. Pairs with `yoeMin`; same LinkedIn-overlay restriction."},"required":false,"description":"Maximum years of experience. Pairs with `yoeMin`; same LinkedIn-overlay restriction.","name":"yoeMax","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false","description":"Return only developers flagged open-to-work on their LinkedIn profile. Requires the LinkedIn overlay, so it restricts to the linked-profile minority we hold. **Defaults to `false`** (no filter)."},"required":false,"description":"Return only developers flagged open-to-work on their LinkedIn profile. Requires the LinkedIn overlay, so it restricts to the linked-profile minority we hold. **Defaults to `false`** (no filter).","name":"openToWork","in":"query"},{"schema":{"type":"string","maxLength":1210,"description":"Seed repositories as `owner/name`. Finds developers who build things comparable to these."},"required":false,"description":"Seed repositories as `owner/name`. Finds developers who build things comparable to these.","name":"repos","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Minimum GitHub follower count."},"required":false,"description":"Minimum GitHub follower count.","name":"minFollowers","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100,"description":"Floor on the cracked score (0-100, the same standing as `details.score.cracked.crackedScore` / devrank), measured against the whole indexed GitHub population. A tunable reputation gate: `minCracked=90` keeps only the top tier. Pairs with `maxCracked` to carve a band. Note this is a FLOOR that filters the fetched window, not a global sort — there is no \"rank by cracked\" order today (the provider does not index the score as sortable)."},"required":false,"description":"Floor on the cracked score (0-100, the same standing as `details.score.cracked.crackedScore` / devrank), measured against the whole indexed GitHub population. A tunable reputation gate: `minCracked=90` keeps only the top tier. Pairs with `maxCracked` to carve a band. Note this is a FLOOR that filters the fetched window, not a global sort — there is no \"rank by cracked\" order today (the provider does not index the score as sortable).","name":"minCracked","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100,"description":"Ceiling on the cracked score (0-100), the upper bound of a cracked RANGE — pair with `minCracked` as the floor. E.g. `minCracked=60&maxCracked=85` targets strong-but-not-famous developers, skipping the very top. Like `minCracked`, this filters the fetched window, it is not a sort."},"required":false,"description":"Ceiling on the cracked score (0-100), the upper bound of a cracked RANGE — pair with `minCracked` as the floor. E.g. `minCracked=60&maxCracked=85` targets strong-but-not-famous developers, skipping the very top. Like `minCracked`, this filters the fetched window, it is not a sort.","name":"maxCracked","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Minimum number of accounts the developer FOLLOWS (the indexed `following` column). A real index filter on the GitHub User lane."},"required":false,"description":"Minimum number of accounts the developer FOLLOWS (the indexed `following` column). A real index filter on the GitHub User lane.","name":"minFollowing","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Maximum number of accounts the developer follows. Pairs with `minFollowing` to band the `following` column."},"required":false,"description":"Maximum number of accounts the developer follows. Pairs with `minFollowing` to band the `following` column.","name":"maxFollowing","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Minimum number of public repositories owned (the indexed `repo_count` column)."},"required":false,"description":"Minimum number of public repositories owned (the indexed `repo_count` column).","name":"minRepos","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Maximum number of public repositories owned. Pairs with `minRepos`."},"required":false,"description":"Maximum number of public repositories owned. Pairs with `minRepos`.","name":"maxRepos","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Minimum TOTAL stars across the developer’s repositories (the indexed account-level `total_stars` column, distinct from a single repo’s stars)."},"required":false,"description":"Minimum TOTAL stars across the developer’s repositories (the indexed account-level `total_stars` column, distinct from a single repo’s stars).","name":"minStars","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Maximum total stars across the developer’s repositories. Pairs with `minStars`."},"required":false,"description":"Maximum total stars across the developer’s repositories. Pairs with `minStars`.","name":"maxStars","in":"query"},{"schema":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Freshness floor: keep only developers whose most recent push (`last_pushed_at`) is on or after this `YYYY-MM-DD` date."},"required":false,"description":"Freshness floor: keep only developers whose most recent push (`last_pushed_at`) is on or after this `YYYY-MM-DD` date.","name":"pushedAfter","in":"query"},{"schema":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Keep only developers whose most recent push (`last_pushed_at`) is on or before this `YYYY-MM-DD` date. Pairs with `pushedAfter`."},"required":false,"description":"Keep only developers whose most recent push (`last_pushed_at`) is on or before this `YYYY-MM-DD` date. Pairs with `pushedAfter`.","name":"pushedBefore","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"GitHub organizations associated with the developer, e.g. `vercel,cloudflare`. Any-of, a hard filter on the indexed `orgs` set. This can include organizations they contribute to, not only ones they are a public member of."},"required":false,"description":"GitHub organizations associated with the developer, e.g. `vercel,cloudflare`. Any-of, a hard filter on the indexed `orgs` set. This can include organizations they contribute to, not only ones they are a public member of.","name":"orgs","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Subject tags the developer must work in, e.g. `distributed-systems,cryptography` — any-of, a HARD filter on the indexed `subjects` set. Distinct from a semantic `q`, which is a soft aim."},"required":false,"description":"Subject tags the developer must work in, e.g. `distributed-systems,cryptography` — any-of, a HARD filter on the indexed `subjects` set. Distinct from a semantic `q`, which is a soft aim.","name":"subjects","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Technologies the developer must have tagged, e.g. `react,rust` — any-of, a HARD filter on the indexed `technologies` set. Distinct from `lang` (repo-language evidence) and `skills` (semantic aim)."},"required":false,"description":"Technologies the developer must have tagged, e.g. `react,rust` — any-of, a HARD filter on the indexed `technologies` set. Distinct from `lang` (repo-language evidence) and `skills` (semantic aim).","name":"techs","in":"query"},{"schema":{"type":"string","maxLength":32,"description":"The cracked-tier label to require (the indexed `crackedTier` column): one of `developing`, `intermediate`, `advanced`, `expert`, `elite` (case-insensitive). A coarser gate than `minCracked`/`maxCracked`."},"required":false,"description":"The cracked-tier label to require (the indexed `crackedTier` column): one of `developing`, `intermediate`, `advanced`, `expert`, `elite` (case-insensitive). A coarser gate than `minCracked`/`maxCracked`.","name":"tier","in":"query"},{"schema":{"type":"string","maxLength":2420,"description":"Employers INFERRED from GitHub signal (the indexed `inferred_employer_name` column), any-of. Distinct from `company` (the LinkedIn-overlay current employer), and does not narrow to the linked-profile minority."},"required":false,"description":"Employers INFERRED from GitHub signal (the indexed `inferred_employer_name` column), any-of. Distinct from `company` (the LinkedIn-overlay current employer), and does not narrow to the linked-profile minority.","name":"employer","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false","description":"Suppress very high-profile accounts, which otherwise dominate a ranking without being realistic hires. A GitHub-lane bias, no LinkedIn overlay needed. **Defaults to `false`** (no suppression)."},"required":false,"description":"Suppress very high-profile accounts, which otherwise dominate a ranking without being realistic hires. A GitHub-lane bias, no LinkedIn overlay needed. **Defaults to `false`** (no suppression).","name":"hideHighProfile","in":"query"},{"schema":{"type":"string","enum":["relevance","cracked","followers","following","total_stars","repo_count","contributions_last_year","last_pushed_at"],"default":"relevance","description":"Result order. `relevance` (default) is best-match-first. `cracked` orders by cracked score (devrank, strongest first) and `followers` by follower count (highest first) — reputation/reach sorts that need no query. On the GitHub User lane these become a true corpus-wide order once the provider indexes the attributes; until then they reorder the fetched page. A non-relevance sort binds only when the query routes to the GitHub User lane. Prefer `sortBy`, which covers every sortable numeric facet; when both are sent `sortBy` wins."},"required":false,"description":"Result order. `relevance` (default) is best-match-first. `cracked` orders by cracked score (devrank, strongest first) and `followers` by follower count (highest first) — reputation/reach sorts that need no query. On the GitHub User lane these become a true corpus-wide order once the provider indexes the attributes; until then they reorder the fetched page. A non-relevance sort binds only when the query routes to the GitHub User lane. Prefer `sortBy`, which covers every sortable numeric facet; when both are sent `sortBy` wins.","name":"sort","in":"query"},{"schema":{"type":"string","enum":["crackedScore","followers","following","total_stars","repo_count","contributions_last_year","last_pushed_at"],"description":"Order results by one numeric developer facet, corpus-wide on the GitHub User lane: `crackedScore` (devrank), `followers`, `following`, `total_stars`, `repo_count`, `contributions_last_year`, or `last_pushed_at` (most recently active first). Every facet sorts strongest/highest/most-recent first — there is no direction knob, the index fixes it per facet. Absent = `relevance` order (unchanged). Binds only on the GitHub User lane; other lanes stay relevance-ordered. Takes precedence over `sort` when both are sent."},"required":false,"description":"Order results by one numeric developer facet, corpus-wide on the GitHub User lane: `crackedScore` (devrank), `followers`, `following`, `total_stars`, `repo_count`, `contributions_last_year`, or `last_pushed_at` (most recently active first). Every facet sorts strongest/highest/most-recent first — there is no direction knob, the index fixes it per facet. Absent = `relevance` order (unchanged). Binds only on the GitHub User lane; other lanes stay relevance-ordered. Takes precedence over `sort` when both are sent.","name":"sortBy","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false","description":"Return only developers we hold an email for (i.e. `hasEmail: true`). **Defaults to `false`** — search stays open like every other filter, so a plain query returns the full ranked pool and fills your `limit`; opt in with `requireEmail=true` when you only want people you can email. FILTERS only; it never returns an address."},"required":false,"description":"Return only developers we hold an email for (i.e. `hasEmail: true`). **Defaults to `false`** — search stays open like every other filter, so a plain query returns the full ranked pool and fills your `limit`; opt in with `requireEmail=true` when you only want people you can email. FILTERS only; it never returns an address.","name":"requireEmail","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false","description":"Return only developers we hold a LinkedIn match for (i.e. `hasLinkedin: true`). **Defaults to `false`** — most searches should stay open, since we only hold a LinkedIn match for a minority of developers and requiring one narrows the pool sharply. Set `true` when resolved identity/company matters more than reach."},"required":false,"description":"Return only developers we hold a LinkedIn match for (i.e. `hasLinkedin: true`). **Defaults to `false`** — most searches should stay open, since we only hold a LinkedIn match for a minority of developers and requiring one narrows the pool sharply. Set `true` when resolved identity/company matters more than reach.","name":"requireLinkedin","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false","description":"Return only developers we resolved a location for (i.e. `hasLocation: true`). **Defaults to `false`**. Set `true` when you can only act on people you can place. FILTERS only; the `hasLocation` flag is free on every row and the resolved `location` object rides `details.contact.location` at `enriched`."},"required":false,"description":"Return only developers we resolved a location for (i.e. `hasLocation: true`). **Defaults to `false`**. Set `true` when you can only act on people you can place. FILTERS only; the `hasLocation` flag is free on every row and the resolved `location` object rides `details.contact.location` at `enriched`.","name":"requireLocation","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":12,"default":4,"description":"How many top repositories to return per developer in `details.githubProfile.repos`, 1-12 (default 4). The default is kept small because the full list reads long and `match.repos` already answers \"why they matched\"."},"required":false,"description":"How many top repositories to return per developer in `details.githubProfile.repos`, 1-12 (default 4). The default is kept small because the full list reads long and `match.repos` already answers \"why they matched\".","name":"repoLimit","in":"query"},{"schema":{"type":"string","maxLength":8000,"description":"Developer ids to leave out, comma separated. Send back what you already have when paging so a short page does not repeat itself."},"required":false,"description":"Developer ids to leave out, comma separated. Send back what you already have when paging so a short page does not repeat itself.","name":"exclude","in":"query"}],"responses":{"200":{"description":"One page of developers, enriched to the requested depth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeveloperSearchResponse"},"example":{"cursor":"N2FmMDdlYWQtYTY5Ni00MTYyLWFkYjgtNjQ2ODJiM2ZhZjI5","cached":false,"countStatus":{"kind":"exact"},"results":[{"id":"1024025","login":"torvalds","name":"Linus Torvalds","avatarUrl":"https://github.com/torvalds.png","hasEmail":true,"hasLinkedin":false,"hasLocation":true,"details":{"githubProfile":{"core":{"bio":null,"currentRole":null,"organization":{"name":"Linux Foundation"},"university":null,"languages":["C","C++","Swift"],"joinedAt":"2011-09-03T15:26:22.000Z","followers":167976,"following":0,"totalStars":255388},"repos":[{"name":"linux","fullName":"torvalds/linux","description":"Linux kernel source tree","language":"C","stars":242463,"owned":true,"commits":1842,"url":"https://github.com/torvalds/linux","subjects":["operating-systems","kernel"],"technologies":["c","make"]}]},"score":{"cracked":{"crackedScore":100,"tier":"Elite"}}},"match":{"repos":[{"fullName":"torvalds/linux","stars":242463,"language":"C","role":"owner"}],"status":"attributed"}}]}}}},"400":{"description":"No query and no narrowing parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Your plan does not include this capability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks search:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"More than 30 requests a minute","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"x-vamo":{"access":"authenticated","audience":"search","rateLimit":{"kind":"fixed","limit":30,"window":"minute","scope":"account","perSeconds":60},"entitlement":"search:read"},"x-audience":["search","agent"],"operationId":"getDevelopersSearch"}},"/v1/developers/enrich":{"get":{"tags":["search"],"summary":"Enrich developers you already hold","description":"Profile and contribution detail for developer ids you already have, in the SAME shape `GET /v1/developers/search` returns — same identity spine, same keyed `details` object. There is no query here, so no `match` block. Use it to deepen rows you took at `core` without re-running the search. Duplicate ids resolve once; an id we hold nothing for is omitted from `results`.\n\n---\n**Access** Authenticated (`search:read`) · **Rate limit** 30 / minute per account","parameters":[{"schema":{"type":"string","maxLength":1625,"description":"Developer ids, comma separated, at most 25. A developer's id is GitHub's public NUMERIC user id, stringified — deterministic, rename-proof, and exactly what `developer.developerId` carries on every response from this API, so ids from search paste straight in. Only have usernames? Use `logins` instead (mixing both is fine). Repeating an id changes nothing and costs nothing: ids are deduplicated before we fetch or bill."},"required":false,"description":"Developer ids, comma separated, at most 25. A developer's id is GitHub's public NUMERIC user id, stringified — deterministic, rename-proof, and exactly what `developer.developerId` carries on every response from this API, so ids from search paste straight in. Only have usernames? Use `logins` instead (mixing both is fine). Repeating an id changes nothing and costs nothing: ids are deduplicated before we fetch or bill.","name":"ids","in":"query"},{"schema":{"type":"string","maxLength":1625,"description":"GitHub usernames, comma separated, at most 25 — the friendly alternative to `ids`, freely mixable with it. Logins resolve to the same developers their numeric ids name; a login that resolves to nobody is omitted from the results and costs nothing, the same contract an unknown id has. Prefer `ids` when you carry results between calls: a login can be renamed and then belongs to someone else."},"required":false,"description":"GitHub usernames, comma separated, at most 25 — the friendly alternative to `ids`, freely mixable with it. Logins resolve to the same developers their numeric ids name; a login that resolves to nobody is omitted from the results and costs nothing, the same contract an unknown id has. Prefer `ids` when you carry results between calls: a login can be renamed and then belongs to someone else.","name":"logins","in":"query"},{"schema":{"type":"string","enum":["core","enriched","deep"],"default":"core","description":"Same ladder as search: `core` profile + repos + cracked score; `enriched` adds LinkedIn identity and socials; `deep` adds the contribution garden — the heavy block, so ask for it only when you need it. AI summaries and per-repo tags are NOT a depth tier: resolve them à-la-carte (their own call), computed once and cross-account cached."},"required":false,"description":"Same ladder as search: `core` profile + repos + cracked score; `enriched` adds LinkedIn identity and socials; `deep` adds the contribution garden — the heavy block, so ask for it only when you need it. AI summaries and per-repo tags are NOT a depth tier: resolve them à-la-carte (their own call), computed once and cross-account cached.","name":"depth","in":"query"},{"schema":{"type":"string","maxLength":605,"description":"À-la-carte facet keys to resolve ON TOP OF the depth tier, comma-separated, at most 5 — e.g. `tags.repos` (folds onto `details.githubProfile.repos[]`). An unknown or non-public key is a 400; a facet already inside the chosen tier is a no-op."},"required":false,"description":"À-la-carte facet keys to resolve ON TOP OF the depth tier, comma-separated, at most 5 — e.g. `tags.repos` (folds onto `details.githubProfile.repos[]`). An unknown or non-public key is a 400; a facet already inside the chosen tier is a no-op.","name":"facets","in":"query"},{"schema":{"type":"string","enum":["full","summary"],"description":"Which shape the contribution garden comes back in. `summary` (the default) is a compact `gardenSummary`: totals, active days and weeks, the last 90 days, the last active day and per-month counts, with `garden` null. `full` is the whole `garden`: every day’s count for the trailing year, for drawing a heatmap.","example":"summary"},"required":false,"name":"garden","in":"query"}],"responses":{"200":{"description":"The developers we hold, enriched to the requested depth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicDeveloperList"},"example":{"results":[{"id":"1024025","login":"torvalds","name":"Linus Torvalds","avatarUrl":"https://github.com/torvalds.png","hasEmail":true,"hasLinkedin":false,"hasLocation":true,"details":{"githubProfile":{"core":{"bio":null,"currentRole":null,"organization":{"name":"Linux Foundation"},"university":null,"languages":["C","C++","Swift"],"joinedAt":"2011-09-03T15:26:22.000Z","followers":167976,"following":0,"totalStars":255388},"repos":[{"name":"linux","fullName":"torvalds/linux","description":"Linux kernel source tree","language":"C","stars":242463,"owned":true,"commits":1842,"url":"https://github.com/torvalds/linux","subjects":["operating-systems","kernel"],"technologies":["c","make"]}]},"score":{"cracked":{"crackedScore":100,"tier":"Elite"}}}}]}}}},"400":{"description":"Neither `ids` nor `logins` named anyone","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Your plan does not include this capability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks search:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"More than 30 requests a minute","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"x-vamo":{"access":"authenticated","audience":"search","rateLimit":{"kind":"fixed","limit":30,"window":"minute","scope":"account","perSeconds":60},"entitlement":"search:read"},"x-audience":["search","agent"],"operationId":"getDevelopersEnrich"}},"/v1/developers/emails":{"get":{"tags":["search"],"summary":"Reveal observed email addresses","description":"The email addresses we observe for developer ids you already hold. Each row is the SAME developer object the other routes return; the addresses land under `details.contact.emails` — no parallel shape is invented. You get EVERY address we observe for a developer. A developer we hold no address for comes back with no `contact.emails` (the namespace is omitted); an input we hold nothing at all for is omitted. Duplicate inputs resolve once.\n\n---\n**Access** Authenticated (`search:read`) · **Rate limit** 30 / minute per account","parameters":[{"schema":{"type":"string","maxLength":1625,"description":"Developer ids, comma separated, at most 25. A developer's id is GitHub's public NUMERIC user id, stringified — deterministic, rename-proof, and exactly what `developer.developerId` carries on every response from this API, so ids from search paste straight in. Only have usernames? Use `logins` instead (mixing both is fine). Repeating an id changes nothing and costs nothing: ids are deduplicated before we fetch or bill."},"required":false,"description":"Developer ids, comma separated, at most 25. A developer's id is GitHub's public NUMERIC user id, stringified — deterministic, rename-proof, and exactly what `developer.developerId` carries on every response from this API, so ids from search paste straight in. Only have usernames? Use `logins` instead (mixing both is fine). Repeating an id changes nothing and costs nothing: ids are deduplicated before we fetch or bill.","name":"ids","in":"query"},{"schema":{"type":"string","maxLength":1625,"description":"GitHub usernames, comma separated, at most 25 — the friendly alternative to `ids`, freely mixable with it. Logins resolve to the same developers their numeric ids name; a login that resolves to nobody is omitted from the results and costs nothing, the same contract an unknown id has. Prefer `ids` when you carry results between calls: a login can be renamed and then belongs to someone else."},"required":false,"description":"GitHub usernames, comma separated, at most 25 — the friendly alternative to `ids`, freely mixable with it. Logins resolve to the same developers their numeric ids name; a login that resolves to nobody is omitted from the results and costs nothing, the same contract an unknown id has. Prefer `ids` when you carry results between calls: a login can be renamed and then belongs to someone else.","name":"logins","in":"query"}],"responses":{"200":{"description":"The developers we hold, each with the addresses we observe","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicDeveloperEmailsList"},"example":{"results":[{"id":"1024025","login":"torvalds","name":"Linus Torvalds","avatarUrl":"https://github.com/torvalds.png","hasEmail":true,"hasLinkedin":false,"hasLocation":true,"details":{"githubProfile":{"core":{"bio":null,"currentRole":null,"organization":{"name":"Linux Foundation"},"university":null,"languages":["C","C++","Swift"],"joinedAt":"2011-09-03T15:26:22.000Z","followers":167976,"following":0,"totalStars":255388},"repos":[{"name":"linux","fullName":"torvalds/linux","description":"Linux kernel source tree","language":"C","stars":242463,"owned":true,"commits":1842,"url":"https://github.com/torvalds/linux","subjects":["operating-systems","kernel"],"technologies":["c","make"]}]},"score":{"cracked":{"crackedScore":100,"tier":"Elite"}},"contact":{"emails":["torvalds@linux-foundation.org"]}}}]}}}},"400":{"description":"Neither `ids` nor `logins` named anyone","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Your plan does not include this capability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks search:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"More than 30 requests a minute","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"x-vamo":{"access":"authenticated","audience":"search","rateLimit":{"kind":"fixed","limit":30,"window":"minute","scope":"account","perSeconds":60},"entitlement":"search:read"},"x-audience":["search","agent"],"operationId":"getDevelopersEmails"}},"/v1/developers/summaries":{"get":{"tags":["search"],"summary":"AI summaries of developers and their repositories","description":"The AI-written plain-language summaries for developer ids you already hold: a one-line `ai.person_summary` (who they are, reading their LinkedIn, projects and full GitHub history) and `ai.repo_summaries` (a short developer-friendly blurb per key repository). Each row is the SAME developer object the other routes return, with the two summary facets in its `details` object — no parallel shape invented. The value is cached across accounts. A developer whose summary is not yet computed comes back `pending` (the job is dispatched); read the same id again to collect the finished `ok` value.\n\nSummaries are NOT a depth tier — depth is how far out a search reaches; this is a separate call, like emails.\n\n---\n**Access** Authenticated (`search:read`) · **Rate limit** 30 / minute per account","parameters":[{"schema":{"type":"string","maxLength":1625,"description":"Developer ids, comma separated, at most 25. A developer's id is GitHub's public NUMERIC user id, stringified — deterministic, rename-proof, and exactly what `developer.developerId` carries on every response from this API, so ids from search paste straight in. Only have usernames? Use `logins` instead (mixing both is fine). Repeating an id changes nothing and costs nothing: ids are deduplicated before we fetch or bill."},"required":false,"description":"Developer ids, comma separated, at most 25. A developer's id is GitHub's public NUMERIC user id, stringified — deterministic, rename-proof, and exactly what `developer.developerId` carries on every response from this API, so ids from search paste straight in. Only have usernames? Use `logins` instead (mixing both is fine). Repeating an id changes nothing and costs nothing: ids are deduplicated before we fetch or bill.","name":"ids","in":"query"},{"schema":{"type":"string","maxLength":1625,"description":"GitHub usernames, comma separated, at most 25 — the friendly alternative to `ids`, freely mixable with it. Logins resolve to the same developers their numeric ids name; a login that resolves to nobody is omitted from the results and costs nothing, the same contract an unknown id has. Prefer `ids` when you carry results between calls: a login can be renamed and then belongs to someone else."},"required":false,"description":"GitHub usernames, comma separated, at most 25 — the friendly alternative to `ids`, freely mixable with it. Logins resolve to the same developers their numeric ids name; a login that resolves to nobody is omitted from the results and costs nothing, the same contract an unknown id has. Prefer `ids` when you carry results between calls: a login can be renamed and then belongs to someone else.","name":"logins","in":"query"}],"responses":{"200":{"description":"The developers we hold, each with its AI summary facets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicDeveloperList"},"example":{"results":[{"id":"1024025","login":"torvalds","name":"Linus Torvalds","avatarUrl":"https://github.com/torvalds.png","hasEmail":true,"hasLinkedin":false,"hasLocation":true,"details":{"githubProfile":{"core":{"bio":null,"currentRole":null,"organization":{"name":"Linux Foundation"},"university":null,"languages":["C","C++","Swift"],"joinedAt":"2011-09-03T15:26:22.000Z","followers":167976,"following":0,"totalStars":255388},"repos":[{"name":"linux","fullName":"torvalds/linux","description":"Linux kernel source tree","language":"C","stars":242463,"owned":true,"commits":1842,"url":"https://github.com/torvalds/linux","subjects":["operating-systems","kernel"],"technologies":["c","make"]}]},"score":{"cracked":{"crackedScore":100,"tier":"Elite"}}}}]}}}},"400":{"description":"Neither `ids` nor `logins` named anyone","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Your plan does not include this capability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks search:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"More than 30 requests a minute","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"x-vamo":{"access":"authenticated","audience":"search","rateLimit":{"kind":"fixed","limit":30,"window":"minute","scope":"account","perSeconds":60},"entitlement":"search:read"},"x-audience":["search","agent"],"operationId":"getDevelopersSummaries"}},"/v1/developers/similar":{"get":{"tags":["search"],"summary":"Find developers similar to one developer","description":"Walks the developer graph out from one seed (co-contribution, co-star, follow edges, semantic repo similarity) and returns the candidates in the SAME shape as search and enrich. A seed with no related developers, or one we hold nothing for, returns an empty list. Candidates whose profile cannot be hydrated are dropped rather than returned bare.\n\nCandidates come back in the graph's own order, each carrying a deterministic `whySimilar` line (shared repositories, a graph bridge, mutual follows). For RANKED candidates with a model-written explanation, use `POST /v1/developers/{id}/similar`.\n\n---\n**Access** Authenticated (`search:read`) · **Rate limit** 30 / minute per account","parameters":[{"schema":{"type":"string","maxLength":64,"description":"The seed developer as an id — the GitHub numeric user id `developer.developerId` carries on every response here. Send this or `login`."},"required":false,"description":"The seed developer as an id — the GitHub numeric user id `developer.developerId` carries on every response here. Send this or `login`.","name":"id","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"The seed developer as a GitHub username. Send this or `id`. A login we cannot resolve returns an empty list."},"required":false,"description":"The seed developer as a GitHub username. Send this or `id`. A login we cannot resolve returns an empty list.","name":"login","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":10,"description":"Candidates to return, 1-50 (default 10)."},"required":false,"description":"Candidates to return, 1-50 (default 10).","name":"limit","in":"query"},{"schema":{"type":"string","enum":["core","enriched","deep"],"default":"core","description":"Same ladder as search: `core` profile + repos + cracked score; `enriched` adds LinkedIn identity and socials; `deep` adds the contribution garden — the heavy block, so ask for it only when you need it. AI summaries and per-repo tags are NOT a depth tier: resolve them à-la-carte (their own call), computed once and cross-account cached."},"required":false,"description":"Same ladder as search: `core` profile + repos + cracked score; `enriched` adds LinkedIn identity and socials; `deep` adds the contribution garden — the heavy block, so ask for it only when you need it. AI summaries and per-repo tags are NOT a depth tier: resolve them à-la-carte (their own call), computed once and cross-account cached.","name":"depth","in":"query"},{"schema":{"type":"string","maxLength":605,"description":"À-la-carte facet keys to resolve ON TOP OF the depth tier, comma-separated, at most 5 — e.g. `tags.repos` (folds onto `details.githubProfile.repos[]`). An unknown or non-public key is a 400; a facet already inside the chosen tier is a no-op."},"required":false,"description":"À-la-carte facet keys to resolve ON TOP OF the depth tier, comma-separated, at most 5 — e.g. `tags.repos` (folds onto `details.githubProfile.repos[]`). An unknown or non-public key is a 400; a facet already inside the chosen tier is a no-op.","name":"facets","in":"query"},{"schema":{"type":"string","enum":["full","summary"],"description":"Which shape the contribution garden comes back in. `summary` (the default) is a compact `gardenSummary`: totals, active days and weeks, the last 90 days, the last active day and per-month counts, with `garden` null. `full` is the whole `garden`: every day’s count for the trailing year, for drawing a heatmap.","example":"summary"},"required":false,"name":"garden","in":"query"}],"responses":{"200":{"description":"Related developers, enriched to the requested depth, each with a why-similar line","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSimilarList"},"example":{"results":[{"id":"1024025","login":"torvalds","name":"Linus Torvalds","avatarUrl":"https://github.com/torvalds.png","hasEmail":true,"hasLinkedin":false,"hasLocation":true,"details":{"githubProfile":{"core":{"bio":null,"currentRole":null,"organization":{"name":"Linux Foundation"},"university":null,"languages":["C","C++","Swift"],"joinedAt":"2011-09-03T15:26:22.000Z","followers":167976,"following":0,"totalStars":255388},"repos":[{"name":"linux","fullName":"torvalds/linux","description":"Linux kernel source tree","language":"C","stars":242463,"owned":true,"commits":1842,"url":"https://github.com/torvalds/linux","subjects":["operating-systems","kernel"],"technologies":["c","make"]}]},"score":{"cracked":{"crackedScore":100,"tier":"Elite"}}}}]}}}},"400":{"description":"Neither `id` nor `login` named a seed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Your plan does not include this capability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks search:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"More than 30 requests a minute","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"x-vamo":{"access":"authenticated","audience":"search","rateLimit":{"kind":"fixed","limit":30,"window":"minute","scope":"account","perSeconds":60},"entitlement":"search:read"},"x-audience":["search","agent"],"operationId":"getDevelopersSimilar"}},"/v1/fit-rank":{"post":{"summary":"Score and rank developers against a role","description":"Score a set of GitHub logins against a role and rank them. Each login is resolved to a developer and scored with one pass over their public work: a fit score (0 off-topic/toy, 1 adjacent, 2 strong direct fit), how readily they could bridge into the role, and how realistically they could be recruited. Results come back best-fit first; equal fits go to the more recruitable, then to confidence. Low gettability is ranked and shown, not hidden. Only deterministically prominent developers (celebrities) are left out, and they are listed in `dropped` with the reason; a login that does not resolve is returned in `misses`, and a candidate the scorer could not read sits at the bottom with `scored:false`. Billed 2 credits per candidate SCORED — dropped and unscored candidates cost nothing, and a call that scores nobody is free.\n\n---\n**Access** Authenticated (`fit_rank:read`) · **Rate limit** 60 / minute per account","tags":["developers"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FitRankRequest"}}}},"responses":{"200":{"description":"Ranked candidates plus unresolved logins","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FitRankResponse"}}}},"400":{"description":"Empty logins, too many, or a malformed login","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"No or invalid credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Plan lacks the capability, or the credit balance is empty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Missing fit_rank:read, or fit ranking is not enabled for this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"x-vamo":{"access":"authenticated","audience":"search","rateLimit":{"kind":"fixed","limit":60,"window":"minute","scope":"account","perSeconds":60},"entitlement":"fit_rank:read"},"x-audience":["search"],"operationId":"postFitRank"}}}}