githunt-ai Search API

The Search API from githunt-ai — 1 operation(s) for search.

Operations 1

POST /v1/search Search developers by location, role, skills, and languages #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/githunt-ai:githunt-ai-search-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

githunt-ai-search-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: GitHunt Search API
  version: 1.0.0
  description: 'Search, look up, and analyze GitHub developers programmatically. GitHunt gives you millisecond access to millions of developers available on GitHub - ranked, scored, and with contact details where publicly available. Every request is billed against your plan''s monthly API call quota; all plans are additionally capped at 2000 calls/day.

    Quotas: Free 50 calls/month (trial), Pro 1000 calls/month, Team 1500 calls/month (unused credits roll over, up to one extra month''s allowance), Enterprise unlimited. Endpoints cost different amounts of quota: search 1 credit, get user 1 credit, evidence report 3 credits (0 when the report is still pending), analyze profile 3 credits, and every /v1/lists operation 0 credits. Endpoints that debit 0 credits still count against the daily cap.'
  contact:
    email: support@githunt.ai
servers:
- url: https://api.githunt.ai
security:
- bearerAuth: []
- apiKeyAuth: []
tags:
- name: Search
paths:
  /v1/search:
    post:
      operationId: searchDevelopers
      summary: Search developers by location, role, skills, and languages
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SearchRequest'
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/QuotaExceeded'
        '500':
          $ref: '#/components/responses/InternalError'
      tags:
      - Search
components:
  schemas:
    TopOssContributions:
      type: array
      maxItems: 3
      description: Notable open-source projects the candidate contributed to
      items:
        type: object
        properties:
          repository:
            type: string
            description: Full repository name (owner/name)
          tier_label:
            type: string
            description: Project prominence tier (e.g. Elite, Popular, Notable)
          commits:
            type: integer
          language:
            type: string
            nullable: true
    SearchResult:
      type: object
      properties:
        login:
          type: string
        score:
          type: number
        profile_score:
          type: number
        tech_stack_score:
          type: number
        activity_score:
          type: number
        github_experience:
          type: number
        matching_keywords:
          type: string
          description: Comma-separated list of matched keywords
        avatar_url:
          type: string
        email:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        company:
          type: string
          nullable: true
        location:
          type: string
          nullable: true
        followers:
          type: integer
        bio:
          type: string
          nullable: true
        profile_url:
          type: string
        blog:
          type: string
        twitter_username:
          type: string
        hireable:
          type: string
          enum:
          - 'Yes'
          - 'No'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        last_active_date:
          type: string
          nullable: true
          description: Date of the candidate's most recent GitHub activity. Usually a date (YYYY-MM-DD); may be a full ISO date-time when derived from fallback sources.
        commits_per_month:
          type: number
          nullable: true
          description: Average commits per month over recent history
        commit_frequency_label:
          type: string
          nullable: true
          description: Human label for commit activity (e.g. Very Active, Active, Unknown)
        semantic_commit_percentage:
          type: number
          nullable: true
          description: Percentage of analyzed commits with semantic/descriptive messages
        commit_message_quality_label:
          type: string
          nullable: true
          description: Human label for commit message quality (e.g. Excellent, Good, Insufficient Data)
        top_repositories:
          $ref: '#/components/schemas/TopRepositories'
        top_oss_contributions:
          $ref: '#/components/schemas/TopOssContributions'
        evidence:
          $ref: '#/components/schemas/Evidence'
        org_affinity:
          $ref: '#/components/schemas/OrgAffinity'
        domain_evidence:
          $ref: '#/components/schemas/DomainEvidence'
        inferred_utc_offset:
          $ref: '#/components/schemas/InferredUtcOffset'
        location_resolution:
          $ref: '#/components/schemas/LocationResolution'
        rank_breakdown:
          type: object
          description: Present when the request named languages, skills, sectors, organizations or domains. Components in [0,1] of the evidence ranking formula rank = base * (1 + 0.6*recency + 0.4*org + 0.5*domain); unknown evidence scores 0 and never lowers a row.
          properties:
            base:
              type: number
            recency:
              type: number
            org:
              type: number
            domain:
              type: number
            final:
              type: number
        score_boosts:
          type: object
          description: 'Ranking boosts applied on top of the base score (present only when non-zero). `score` stays clamped to 0-100. When the request names languages, skills, sectors, organizations or domains, ordering is not this boosted value: results are ranked by the base score scaled by how recently the requested skills were used and how strongly the candidate matches the requested employers and domains, so a result may sit above one with a higher `score`.'
          properties:
            org_affinity:
              type: number
            domain_evidence:
              type: number
    ErrorResponse:
      type: object
      required:
      - success
      - error
      properties:
        success:
          type: boolean
          const: false
        error:
          type: object
          required:
          - code
          - message
          properties:
            code:
              type: string
              enum:
              - unauthorized
              - quota_exceeded
              - invalid_request
              - not_found
              - internal
            message:
              type: string
    LocationResolution:
      type: object
      description: 'How the candidate''s stated base resolved at the run timestamp. Attached to every result whenever the request carried an exclusion or a `skillRecency` filter. Discovery stays permissive: `ambiguous` and `unresolved` candidates are still returned, and belong in a screening queue rather than a geographically eligible shortlist. Commit timezone is never `resolved` - an author-side commit offset can support discovery but cannot establish a country or a current base, and never excludes a candidate on its own - see `screening_reason`.'
      properties:
        status:
          type: string
          enum:
          - resolved
          - ambiguous
          - unresolved
        country:
          type: string
          nullable: true
          description: Null unless the stated location settles a single country.
        utc_offset:
          type: object
          nullable: true
          description: Offset band in hours at the run timestamp, daylight saving applied. `min` equals `max` when the location pins a single zone.
          properties:
            min:
              type: number
            max:
              type: number
        basis:
          type: string
          nullable: true
          enum:
          - stated_location
          - commit_timezone
        screening_reason:
          type: string
          nullable: true
          enum:
          - inferred_offset_in_excluded_band
          description: 'Why this candidate needs a screening question before being counted as geographically eligible. `inferred_offset_in_excluded_band` means the stated location did not resolve and the candidate''s commit timezone falls inside the `excludeUtcOffsets` band the request asked to exclude. Such candidates are deliberately returned rather than excluded: a commit offset cannot establish a country or a current base, so it is a question to ask, not an answer. Null when no screening flag applies.'
        observed_at:
          type: string
          format: date-time
          description: The run's frozen evaluation instant.
    SearchRequest:
      type: object
      description: At least one of `location`, `locations`, or `regions` is required.
      properties:
        location:
          type: string
          example: Poland
        role:
          type: string
          example: backend
        skills:
          type: array
          items:
            type: string
          maxItems: 20
          example:
          - go
          - kubernetes
        languages:
          type: array
          items:
            type: string
          maxItems: 10
          example:
          - Go
        minExperienceYears:
          type: integer
          minimum: 0
          maximum: 50
        isHireable:
          type: boolean
        strictSkills:
          type: boolean
          default: false
        includeUnlocated:
          type: boolean
          default: false
          description: When true, also search candidates indexed with no stated location. Their location is unknown, so they are returned as screening leads and can never be counted as geographically verified; `meta.coverage.unlocated_included` marks a response that contains them.
        maxResults:
          type: integer
          minimum: 1
          maximum: 100
          default: 25
        offset:
          type: integer
          minimum: 0
          maximum: 200
          default: 0
          description: Number of top-ranked candidates to skip, for paging. Use with maxResults to fetch the next page. Consecutive pages never overlap.
        excludeLogins:
          type: array
          items:
            type: string
          maxItems: 500
          example:
          - octocat
          - torvalds
          description: GitHub logins to leave out of results, e.g. candidates already seen in a prior call. Use for dedup across searches. Case-insensitive; invalid entries are dropped rather than rejected.
        excludeLocations:
          type: array
          items:
            type: string
          maxItems: 50
          example:
          - India
          description: Countries or cities to exclude, matched the same way as the location parameter (aliases and native names included).
        excludeUtcOffsets:
          type: object
          description: Exclude candidates whose stated location resolves entirely within this UTC offset band, in hours. A location that only partially overlaps the band, or can't be resolved, is kept (not excluded) - a candidate whose commit timezone falls inside the band but whose location is unresolvable comes back flagged with `location_resolution.screening_reason`, never dropped.
          properties:
            min:
              type: number
              minimum: -12
              maximum: 14
            max:
              type: number
              minimum: -12
              maximum: 14
          required:
          - min
          - max
          example:
            min: 0
            max: 5
        locations:
          type: array
          items:
            type: string
          maxItems: 10
          example:
          - Berlin
          - Warsaw
          description: Additional cities/countries to search in one call, freeform like `location`, merged with it (max 10 combined). Live GitHub crawl only covers the first location; further locations are served from the candidate pool only. At least one of `location`, `locations`, or `regions` is required.
        regions:
          type: array
          items:
            type: string
            enum:
            - north-america
            - latin-america
            - south-america
            - europe
            - western-europe
            - eastern-europe
            - nordics
            - dach
            - benelux
            - iberia
            - uk-ireland
            - middle-east
            - africa
            - apac
            - east-asia
            - southeast-asia
            - south-asia
            - oceania
            - americas
            - emea
            - worldwide
          maxItems: 3
          example:
          - apac
          description: Named region shortcuts that expand to their member countries, merged with `location`/`locations` (max 10 combined locations after expansion; extras are dropped). Case-insensitive. A request whose region names are all unknown and that carries no `location` is rejected with `invalid_request`.
        organizations:
          type: array
          items:
            type: string
          maxItems: 20
          example:
          - stripe
          - adyen
          description: GitHub org logins to check candidates' employer affinity against. Boosts matching candidates' rank unless `requireOrgAffinity` is true.
        sectors:
          type: array
          items:
            type: string
            enum:
            - adtech
            - ai-ml
            - banking
            - cloud
            - cybersecurity
            - ecommerce
            - fintech
            - gaming
            - healthtech
            - media
            - mobility
            - payments
          maxItems: 5
          example:
          - payments
          description: Industry sectors to check candidates' employer affinity against, via GitHunt's employer graph (public GitHub orgs mapped to companies and sectors).
        requireOrgAffinity:
          type: boolean
          default: false
          description: When true, only return candidates matching one of the given `organizations`/`sectors` (hard filter) instead of just boosting their rank.
        domains:
          type: array
          items:
            type: string
            enum:
            - payments
            - healthcare
            - adtech
          maxItems: 3
          example:
          - payments
          description: Domain vocabulary packs to score candidates' repos/bio against for subject-matter evidence (e.g. core payments-processing terminology, not just the word "payments").
        skillRecency:
          type: array
          minItems: 1
          maxItems: 10
          items:
            $ref: '#/components/schemas/SkillRecencyEntry'
          example:
          - skill: Scala
            usedWithinYears: 3
          description: 'Filter on public skill activity. Entries are ANDed: a candidate must satisfy every entry to be returned. Only candidates whose signals positively support every entry are returned, and only they occupy a slot in the per-location selection the search scores, so a candidate with evidence is never crowded out by higher-activity candidates without it. Candidates whose signals cannot answer the question are `unknown` and are left out of the results (and queued for enrichment), which is not a negative finding - see `meta.skill_recency`. `unknown` covers a signal that is missing, failed, expired (signals are refreshed on a 30-day cycle, and one older than that no longer answers a strict filter) or partial (the years the answer depends on could not be fetched). Malformed entries are an uncharged `invalid_request`. When `skillRecency` is set, the search is served from the candidate pool alone: a live GitHub row carries no derived signals and could only ever be `unknown`.'
        excludeList:
          type: string
          pattern: ^[a-z0-9][a-z0-9_-]{0,63}$
          example: vami-scala-payments
          description: 'Name of a seen list (see /v1/lists) whose logins are merged into `excludeLogins` for this search, so a rerun of the same brief never returns candidates the account already recorded. Only permanent `seen` entries and claims that have not expired are excluded: an interrupted run''s candidates are rediscoverable as soon as the claim lapses. The server-side list is bounded at 5000 eligible logins rather than the 500-entry client cap; `meta.exclude_list.truncated` reports when that bound was hit. An unknown list is a `not_found` before any quota is charged, so create the list first with an empty `POST /v1/lists/{name}/logins`.'
    SkillRecencyEntry:
      type: object
      description: One skill-activity predicate. At least one of `minActiveYears` or `usedWithinYears` is required; both may be given.
      required:
      - skill
      properties:
        skill:
          type: string
          minLength: 1
          maxLength: 64
          example: Scala
          description: Language or skill name. Common aliases resolve to the canonical GitHub Linguist name (ts, js, py, rb, kt, rs, sh, cpp, c#, golang).
        minActiveYears:
          type: integer
          minimum: 1
          maximum: 9
          description: Minimum number of distinct calendar years with public activity in this skill (a year counts at five or more commits). This is a public-activity measure, never elapsed or commercial tenure.
        usedWithinYears:
          type: integer
          minimum: 1
          maximum: 9
          description: Require dated activity inside the rolling window of this many years ending at the request's UTC timestamp. Calendar-year subtraction in UTC, clamping Feb 29 to Feb 28 in a non-leap target year; the cutoff day itself counts as inside the window.
    SearchResponse:
      type: object
      properties:
        success:
          type: boolean
          const: true
        data:
          type: object
          properties:
            matchedCount:
              type: integer
              description: Results in this page.
            totalCount:
              type: integer
            offset:
              type: integer
              description: Echoes the applied offset.
            locationSuggestions:
              type: array
              items:
                type: string
              description: Similar supported locations ("City, Country"), present only when the search returned zero results because the location matched no known city or country.
            results:
              type: array
              items:
                $ref: '#/components/schemas/SearchResult'
        meta:
          type: object
          properties:
            requestId:
              type: string
            dataSource:
              type: string
              example: candidate_pool
            quota:
              $ref: '#/components/schemas/Quota'
            coverage:
              type: object
              description: What the search actually read, so an empty page is never mistaken for an exhaustive absence.
              properties:
                locations_searched:
                  type: integer
                locations_dropped:
                  type: integer
                  description: Locations left unsearched because region expansion exceeded the per-request location cap.
                partial:
                  type: boolean
                  description: True when retrieval was bounded (a capped partition, a per-location read cap, a timed-out location read, or a failed pool read).
                candidates_fetched:
                  type: integer
                  description: Pool candidates that passed the request's exclusions across all searched locations, before ranking.
                candidates_scored:
                  type: integer
                  description: Candidates handed to the ranker. Scaled with the number of locations under a per-request ceiling and the time budget, so a region search does not split one location's budget across its countries.
                unlocated_included:
                  type: boolean
                  description: Present only when the request set `includeUnlocated`. Results may include candidates with no stated location, which are screening leads, not verified geography.
            skill_recency:
              type: object
              description: Present only when the request carried `skillRecency`. Counts come from every candidate seen in the queried partitions, not from the returned page.
              properties:
                evaluated:
                  type: integer
                supported:
                  type: integer
                unknown:
                  type: integer
                  description: Candidates whose signals could not answer the filter, because they are missing, failed, expired (older than the 30-day signal refresh window) or partial (the years the answer depends on could not be fetched). Not a negative finding; they are excluded from the scored selection, and queued for enrichment so a later search can judge them on evidence.
                contradicted:
                  type: integer
                  description: Candidates the signals positively rule out. A bound that only an unfetched year could have met is `unknown`, not `contradicted`.
                partial:
                  type: boolean
                  description: True when retrieval was bounded (a capped partition or a failed pool read), so an empty page is not evidence of absence.
            exclude_list:
              type: object
              description: Present only when the request carried `excludeList`.
              properties:
                name:
                  type: string
                logins:
                  type: integer
                  description: Logins merged into the exclusion from the list.
                truncated:
                  type: boolean
                  description: True when the list exceeded the 5000-login read bound.
    DomainEvidence:
      type: object
      description: Present when `domains` were given, keyed by pack name (e.g. "payments").
      additionalProperties:
        type: object
        properties:
          score:
            type: number
          tier:
            type: string
            enum:
            - core
            - adjacent
            - generic
            - none
            description: Strongest vocabulary tier the candidate actually matched. Ranking uses this rather than `score`, because a score sums tiers and so cannot separate several generic words from one core term.
          summary:
            type: string
            example: 'Core: settlement, PSP; adjacent: checkout, refund'
          core_terms:
            type: array
            items:
              type: string
    InferredUtcOffset:
      type: object
      nullable: true
      description: UTC offset inferred from the candidate's own commit author timestamps, used when GitHub's `location` field is empty or unresolvable. Null when no signal is available.
      properties:
        offset:
          type: number
          example: -10
        confidence:
          type: string
          enum:
          - none
          - low
          - medium
          - high
        sample_size:
          type: integer
          description: Number of commits the inference was based on
        share:
          type: number
          description: Fraction of sampled commits at the dominant offset
        latest_commit:
          type: string
          format: date-time
    Quota:
      type: object
      properties:
        used:
          type: integer
        limit:
          type: integer
          description: -1 means unlimited
        month:
          type: string
          example: 2026-07
        cost:
          type: integer
          description: 'Credits this request debited (search: 1, get user: 1, evidence report: 3 when a report is returned and 0 while pending, analyze profile: 3, list operations: 0). `used` already reflects this charge.'
          example: 1
        rollover:
          type: integer
          description: Unused credits banked from the previous month and available on top of `limit` this month (`remaining` = limit + rollover - used). Only present on the Team plan, capped at one extra month's allowance (so at most 2x the allowance is usable in a month).
          example: 340
    OrgAffinity:
      type: object
      description: Present when `organizations` or `sectors` were given in the request.
      properties:
        score:
          type: number
        matches:
          type: array
          items:
            type: object
            properties:
              org:
                type: string
              company:
                type: string
              sector:
                type: string
    TopRepositories:
      type: array
      maxItems: 3
      description: The candidate's top repositories, as shown on the website candidate card
      items:
        type: object
        properties:
          name:
            type: string
          stars:
            type: integer
          language:
            type: string
            nullable: true
    Evidence:
      type: array
      description: Where each matched skill/keyword was found on the candidate.
      items:
        type: object
        properties:
          keyword:
            type: string
          source:
            type: string
            enum:
            - repo_name
            - repo_description
            - repo_language
            - bio
            - company
            - skill_fallback
          repo:
            type: string
            description: Bare repository name (no owner), present when the match came from a repository. Use `top_repositories` or the evidence report for owner-qualified names.
          snippet:
            type: string
            description: Short surrounding text for bio/company matches
  responses:
    InternalError:
      description: Unexpected server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Missing, invalid, or revoked API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    QuotaExceeded:
      description: Monthly or daily quota exceeded
      headers:
        Retry-After:
          schema:
            type: integer
          description: Seconds until the quota resets
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'Authorization: Bearer ghk_live_...'
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key