Documentation navigation

Vamo API

Search GitHub developers by what they have built, resolve identities to full profiles, and enrich them with the signals you need. Call it from your own code, or connect an agent to the Vamo MCP server. Every endpoint below documents its access requirements and rate limits alongside its schemas.

Building with an agent?

Copy one line into your coding agent. It fetches the setup prompt, connects to the Vamo MCP server, and asks you for a setup line from your dashboard when it needs access.

Start here

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.

Base URL

https://api.vamotalent.ai

Authentication

Every non-public endpoint takes a bearer credential:

Authorization: Bearer vamo_sk_...

API keys are prefixed vamo_sk_ and are scoped to one account. The same key is also accepted in an X-Api-Key header. Humans signed in to the Vamo app use session tokens over the same header; keys and sessions follow one usage model.

Get a key

Sign in at https://app.vamotalent.ai, open Settings, then API Keys, and choose Create key. Name it for the person or agent that will use it and grant only the permissions it needs. Each operation names the one permission it requires in its x-vamo.entitlement field: a key with Search set to Read holds search:read, which covers search, enrich, similar, summaries and emails. The secret is shown once. A lost key is replaced by creating a new one and revoking the old one; permissions can be edited at any time and apply to the next request.

Keep the key safe

Hold the key in an environment variable named VAMO_API_KEY, loaded from a private file or an operating-system keychain, and send it only as a header to this host. Keep it out of chat messages, URLs, logs, shared documents and source control. An agent should look for VAMO_API_KEY before asking a person for a key, and should never echo it back. A key that has appeared in a shared chat, a screen share or a recording should be revoked and replaced.

Network access

Everything here is served from one host: api.vamotalent.ai, over HTTPS. That includes the API, /openapi.json and /docs. A sandbox, proxy or firewall that restricts outbound requests needs that single host on its allowlist. GET /openapi.json needs no key, so it is the right first request to prove the network path before a credential is involved.

Errors

Status codes are precise: 401 no credential reached the API or it is invalid or revoked, 403 the credential lacks the required entitlement or the account does not have the feature, 402 the plan or balance does not cover the call, 429 a rate limit or usage limit is exhausted.

Every error body carries a stable code and a human message. Branch on code, never on the numeric status, and read the rest of the body: entitlement names the missing permission on a 403, reason distinguishes the cases that share a code, retryAfterSeconds says how long to wait on a 429, and remedy, when present, points at the way out.

Some refusals can only be cleared by a person, in a browser: connecting a GitHub account is one. Such a refusal can carry an action: { id, kind, url, expiresAt }. Give action.url to the person you are working for, or open it for them. They sign in to Vamo and take the step on that page. When they say they are done, send the refused request again: it goes through if the step is done, and answers with a new link if not. The link is theirs alone and works for 15 minutes.

Working from this spec

openapi.json is the source of truth for every route, parameter and response field, and it is written to be read by an agent as well as a person. Before calling an operation, read its parameters and their descriptions here; they state what each filter reaches and how to read what comes back. Guides and skills describe method and defer to this document for the surface.

A search can take ten to twenty seconds. Use a request timeout of at least sixty seconds and let a call finish before retrying it.

Credits

Paid calls spend credits from the account's pool. A developer call costs 1 credit per developer it returns, plus each facet cell delivered for that developer. depth picks a bundle of facet cells (core, enriched, deep, each a superset of the last), and facets adds cells on top, so the price per person grows with depth. A cell the account already owns bills 0, and a call that returns nobody costs nothing.

Price a request before sending it from GET /v2/pricing/catalog: it is free, needs no key, and is read from the same table the biller charges from. skus and facets hold the per-cell prices, bundles holds what each depth tier contains, addOns prices the AI summaries (sold by name, outside the tiers), and creditUsd turns credits into dollars. Every paid response states x-cost, what that call cost. GET /v1/account/credits reads the balance, the period grant and when it refreshes; read it before a large batch. An empty balance is a 402 whose remedy points at the top-up.

Rate limiting

Every 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.

Versioning

The API is versioned in the path. Developer search, lookup, enrichment and deep research are /v2 (/v2/developers/*, /v2/deep-research/*); the /v1 developer and deep-research routes still answer but are deprecated: each answers with a Deprecation: true header and a Link header naming its /v2 successor, and they are no longer in this document. 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.

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.

Quickstart

Search for developers by what they have built. A search is one JSON body: filters hold the facts (place, employer, school, title, languages), rank_by holds the meaning, and each developer comes back with the evidence behind the match.

curl https://api.vamotalent.ai/v2/developers/search \
  -H "Authorization: Bearer vamo_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "rank_by": ["v", "ANN", ["Embed", "distributed databases in Rust"]],
    "filters": ["And", [
      ["location_ids", "ContainsAny", {"place": ["San Francisco"]}],
      ["is_bot", "Eq", false],
      ["is_org_account", "Eq", false]
    ]],
    "limit": 10
  }'

Places, companies and schools are written by name ({"place": [...]}, {"company": [...]}, {"school": [...]}) and resolved for you; a city means its metro unless you add "scope": "city". With no meaning to rank by, "sort": "devrank" returns the strongest people first. POST /v2/developers/search/validate checks and compiles the same body for free, and GET /v2/developers/fields lists every field a query can use and for what.

Exclude with ["Not", f]. ["Not", ["current_company_ids", "ContainsAny", {"company": ["X"]}]] drops only people who work at X now; ["Not", ["former_company_ids", "ContainsAny", {"company": ["X"]}]] drops anyone who ever worked there. To exclude a word in a title, write ["Not", ["role_title", "ContainsAnyToken", "intern"]] (a pattern starting with * is refused). Token operators take one space-separated string, e.g. ["current_title", "ContainsAnyToken", "engineer developer"]; a list of words is joined into that string, in order. With several lanes under "queries", top-level "filters" apply to every lane.

More request shapes

# Engineers who worked at Cloudflare (past or present), in the Denver area, strongest first, at full depth
curl https://api.vamotalent.ai/v2/developers/search \
  -H "Authorization: Bearer vamo_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "filters": ["And", [
      ["former_company_ids", "ContainsAny", {"company": ["Cloudflare"]}],
      ["location_ids", "ContainsAny", {"place": ["Denver"]}],
      ["is_bot", "Eq", false],
      ["is_org_account", "Eq", false]
    ]],
    "sort": "devrank",
    "depth": "enriched"
  }'

# Developers like one you already know
curl https://api.vamotalent.ai/v2/developers/similar \
  -H "Authorization: Bearer vamo_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"like_person": "jonhoo"}'

# Full profiles for people you already know, by GitHub login
curl https://api.vamotalent.ai/v2/developers \
  -H "Authorization: Bearer vamo_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"logins": ["torvalds"], "depth": "enriched"}'

depth is core (the default), enriched or deep; each step returns more of the profile. A page ends with a cursor: send it back with the same body for the next page.

Deep research reports as PDF

A finished deep-research report (developer or repository) downloads as a PDF: the report page itself, printed, with your account's logo and name in the header. It is free, and it needs a finished report, so start the research with POST /v2/deep-research/jobs and poll it until it is done first.

# The file itself
curl -o report.pdf https://api.vamotalent.ai/v2/deep-research/reports/developers/torvalds/pdf \
  -H "Authorization: Bearer vamo_sk_..."

# A link to hand to a person: public, works for 15 minutes
curl "https://api.vamotalent.ai/v2/deep-research/reports/repos/vercel/next.js/pdf?delivery=link" \
  -H "Authorization: Bearer vamo_sk_..."

delivery=link answers { "url", "expiresAt", "bytes" }; the url opens the file with no credential, so an agent can pass it straight to a person. Accept: application/pdf on the report reads (GET /v2/deep-research/reports/developers/{login} and /repos/{owner}/{name}) answers the same file. A report version renders once, so asking again is fast; a newer report or a new account logo renders afresh.

Authentication

Every request is authenticated with an API key passed as a bearer token. Once your plan includes API access (book a call to set it up), create a key from your workspace settings, then send it in the Authorization header:

-H 'Authorization: Bearer vamo_sk_YOUR_KEY'

See the authentication guide for scoping a key, what each refusal means, and signed requests.

Reference

Search

Developers

Developers

Resolve identifiers (handles, GitHub or LinkedIn URLs, names, repos) to developer profiles, and enrich those profiles with facets. Enrichment is available inline for values Vamo already holds and as a durable report for values that must be computed.

Deep research

Full-depth GitHub research on a named developer or repository, persisted as a report the whole account can read, as JSON or as a PDF (the file itself, or a 15-minute download link). Jobs run in rounds and report per-subject outcomes, so a partial result is a normal answer rather than an error.

Discover

Curated lists of developers Vamo publishes, each with the search requests that find them. No credential required.

Pipeline

Shortlists

Ordered lists of developers you are considering. Add, move, copy, and remove members, pin the repository that makes the case for each one, keep notes about the list, and see which lists a developer is already on.

Account

Pricing

Public pricing: the sellable plans, the dollars-per-credit rate, and the per-facet price table. No credential required.