openapi: 3.1.0
info:
  title: GitHunt 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, Enterprise unlimited.
  contact:
    email: support@githunt.ai
servers:
  - url: https://api.githunt.ai
security:
  - bearerAuth: []
  - apiKeyAuth: []
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'
  /v1/users/{login}:
    get:
      operationId: getDeveloper
      summary: Get a single developer's profile by GitHub username
      parameters:
        - name: login
          in: path
          required: true
          schema:
            type: string
          description: GitHub username
      responses:
        '200':
          description: Developer profile
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/QuotaExceeded'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/profile/analyze:
    post:
      operationId: analyzeProfile
      summary: Run a deep profile analysis for a single GitHub username
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [username]
              properties:
                username:
                  type: string
                  description: GitHub username to analyze
      responses:
        '200':
          description: Profile analysis
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProfileAnalyzeResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/QuotaExceeded'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: "Authorization: Bearer ghk_live_..."
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key
  responses:
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Missing, invalid, or revoked API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: No matching developer
      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'
    InternalError:
      description: Unexpected server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  schemas:
    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
    Quota:
      type: object
      properties:
        used:
          type: integer
        limit:
          type: integer
          description: "-1 means unlimited"
        month:
          type: string
          example: "2026-07"
    SearchRequest:
      type: object
      required: [location]
      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
        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.
    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'
    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
    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
    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'
    UserResponse:
      type: object
      properties:
        success:
          type: boolean
          const: true
        data:
          type: object
          properties:
            username:
              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
              example: "rust, python, javascript"
            bio:
              type: string
              nullable: true
            profile_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
            blog:
              type: string
              nullable: true
            twitter_username:
              type: string
              nullable: true
            created_at:
              type: string
              format: date-time
            updated_at:
              type: string
              format: date-time
            hireable:
              type: string
              enum: ["Yes", "No"]
            avatar_url:
              type: string
            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'
    ProfileAnalyzeResponse:
      type: object
      properties:
        success:
          type: boolean
          const: true
        data:
          type: object
          description: >
            Deep analysis payload. Top-level keys: profile (basic profile facts),
            emails ({emails: [{address, sources, commitCount, isPrimary}]}),
            commitQuality, repositories, activity, roleMatch (ranked array of
            role fits with score breakdowns), proficiency ({level, score,
            experienceYears}), scores (best-role score with detailed breakdown),
            badges, summary. Sub-shapes may gain fields over time (additive only).
          additionalProperties: true
          properties:
            proficiency:
              type: object
              properties:
                level:
                  type: string
                  example: Senior
                score:
                  type: number
                experienceYears:
                  type: number
            emails:
              type: object
              properties:
                emails:
                  type: array
                  items:
                    type: object
                    properties:
                      address:
                        type: string
                      sources:
                        type: array
                        items:
                          type: string
                      isPrimary:
                        type: boolean
            roleMatch:
              type: array
              items:
                type: object
                properties:
                  role:
                    type: string
                  displayName:
                    type: string
                  score:
                    type: number
