openapi: 3.0.3
info:
  title: RobotDomainSearch API
  version: 0.3.0
  description: |
    Domain availability API for developers and AI agents.
    
    Check domain availability across 511 TLDs organized in 15 categories, list supported TLDs,
    get registration links, and look up ENS names.
    
    No authentication required. Rate limited to 60 requests/minute per IP.
  contact:
    email: api@robotdomainsearch.com
    url: https://robotdomainsearch.com
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: https://api.robotdomainsearch.com
    description: Main API (includes ENS endpoints at /v1/ens/*)

paths:
  /v1/check:
    get:
      operationId: checkDomainAvailability
      summary: Check domain availability
      description: |
        Check if a domain name is available for registration across multiple TLDs.
        
        The `tld` parameter supports comma-separated values for bulk checking (max 20).
        The `category` parameter checks all TLDs in a category.
        If neither is specified, checks the Top 20 TLDs.
        
        Single TLD returns a flat response. Multiple TLDs return a bulk response with summary counts.
      parameters:
        - name: name
          in: query
          required: true
          description: Domain name to check (without TLD)
          schema:
            type: string
            example: mycoolstartup
        - name: tld
          in: query
          required: false
          description: TLD(s) to check. Supports comma-separated values (e.g., "com,net,io"). Max 20.
          schema:
            type: string
            example: com,net,io
        - name: category
          in: query
          required: false
          description: Check all TLDs in a category (e.g., "technology"). Use GET /v1/tlds for available categories.
          schema:
            type: string
            example: technology
        - name: domain
          in: query
          required: false
          description: |
            Domainr-compatible format. Full domain(s) to check (e.g., "example.com" or "example.com,example.net").
            Alternative to using name+tld parameters.
          schema:
            type: string
            example: example.com,example.net
      responses:
        '200':
          description: Domain availability results
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/CheckResponse'
                  - $ref: '#/components/schemas/BulkCheckResponse'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/tlds:
    get:
      operationId: listTLDs
      summary: List supported TLDs
      description: |
        Get all top-level domains supported by RobotDomainSearch, organized by category.
        
        Default response includes all categories and a sorted list of all TLDs.
        Use `category` to filter to a single category.
        Use `type` to get a flat list filtered by gTLD or ccTLD.
      parameters:
        - name: type
          in: query
          required: false
          description: Filter by TLD type (returns flat list)
          schema:
            type: string
            enum: [gTLD, ccTLD]
            example: gTLD
        - name: category
          in: query
          required: false
          description: Filter by category name
          schema:
            type: string
            example: technology
      responses:
        '200':
          description: List of supported TLDs
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TLDsResponse'
        '400':
          description: Invalid type or category filter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/register:
    get:
      operationId: getRegistrationLinks
      summary: Get registration links
      description: Get links to register a domain at popular registrars.
      parameters:
        - name: domain
          in: query
          required: true
          description: Full domain name (e.g., example.com)
          schema:
            type: string
            example: mycoolstartup.com
        - name: registrar
          in: query
          required: false
          description: Filter to a specific registrar
          schema:
            type: string
            enum: [porkbun, namecheap, godaddy]
            example: porkbun
      responses:
        '200':
          description: Registration links
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegisterResponse'
        '400':
          description: Invalid domain or registrar
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/aftermarket/{domain}:
    get:
      operationId: checkAftermarket
      summary: Check domain aftermarket listings
      description: |
        Check if a domain is listed for sale on aftermarket marketplaces.
        Aggregates real-time data from multiple providers (Sedo, Dynadot) using
        a parallel fan-out architecture with graceful degradation.
      parameters:
        - name: domain
          in: path
          required: true
          description: Domain name to check (e.g., example.com)
          schema:
            type: string
            example: premium.com
        - name: sources
          in: query
          required: false
          description: Comma-separated list of sources to query (e.g., "sedo,dynadot")
          schema:
            type: string
            example: sedo,dynadot
        - name: timeout
          in: query
          required: false
          description: Per-source timeout in milliseconds (1–15000, default 5000)
          schema:
            type: integer
            default: 5000
            example: 5000
        - name: currency
          in: query
          required: false
          description: Preferred display currency (default USD)
          schema:
            type: string
            default: USD
            example: USD
      responses:
        '200':
          description: Aftermarket listing results (may include partial failures)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AftermarketResponse'
        '400':
          description: Invalid domain format
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '405':
          description: Method not allowed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '501':
          description: All requested sources are not configured
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AftermarketResponse'
        '503':
          description: All sources failed / service not initialized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/name-search-presence:
    get:
      operationId: nameSearchPresence
      summary: Check search engine presence for a name or brand
      description: |
        Check how visible a name or brand is across major search engines.
        Returns a presence score (0–100), per-engine results, signal detection,
        and an AI-generated summary. Useful for evaluating whether a name is
        already established online before registering a domain.
      parameters:
        - name: name
          in: query
          required: true
          description: Name or brand to search for
          schema:
            type: string
            example: mycoolstartup
        - name: engines
          in: query
          required: false
          description: Comma-separated list of engines to query (brave, perplexity). Default all.
          schema:
            type: string
            example: brave,perplexity
        - name: timeout
          in: query
          required: false
          description: Request timeout in milliseconds
          schema:
            type: integer
            example: 5000
      responses:
        '200':
          description: Name search presence results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NameSearchPresenceResponse'
        '400':
          description: Missing or invalid name parameter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '405':
          description: Method not allowed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: All engines failed / service unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/whois:
    get:
      operationId: whoisLookup
      summary: WHOIS / RDAP domain lookup
      description: |
        Look up WHOIS / RDAP data for a domain name. Returns registrar, dates,
        nameservers, registration status, and more.
      parameters:
        - name: domain
          in: query
          required: true
          description: Full domain name to look up (e.g., example.com)
          schema:
            type: string
            example: example.com
      responses:
        '200':
          description: WHOIS data for the domain
          content:
            application/json:
              schema:
                type: object
        '400':
          description: Invalid domain format
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/intel:
    get:
      operationId: domainIntel
      summary: Domain intelligence
      description: |
        Get domain intelligence including parked detection and screenshots.
      parameters:
        - name: domain
          in: query
          required: true
          description: Full domain name (e.g., example.com)
          schema:
            type: string
            example: example.com
      responses:
        '200':
          description: Domain intelligence results
          content:
            application/json:
              schema:
                type: object
        '400':
          description: Invalid domain format
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/auctions:
    get:
      operationId: browseAuctions
      summary: Browse live domain auctions
      description: |
        Browse live domain auctions aggregated from Namecheap, Sedo, and Dynadot.
        Filter by TLD, price, bids, and keyword. Sort by price, end time, or quality score.
      parameters:
        - name: tld
          in: query
          required: false
          description: Filter by TLD (e.g., com)
          schema:
            type: string
            example: com
        - name: keyword
          in: query
          required: false
          description: Search keyword
          schema:
            type: string
        - name: hot
          in: query
          required: false
          description: Show trending/hot auctions
          schema:
            type: boolean
            example: true
        - name: limit
          in: query
          required: false
          description: Number of results to return
          schema:
            type: integer
            default: 25
            example: 10
        - name: sort
          in: query
          required: false
          description: Sort field
          schema:
            type: string
            enum: [price, end_time, bids, quality_score]
        - name: order
          in: query
          required: false
          description: Sort order
          schema:
            type: string
            enum: [asc, desc]
      responses:
        '200':
          description: Auction listings
          content:
            application/json:
              schema:
                type: object

  /v1/ens/check:
    get:
      operationId: checkENSAvailability
      summary: Check ENS name availability
      description: |
        Check if an ENS (Ethereum Name Service) name is available for registration
        and get pricing information. ENS is proxied through the main API.
      parameters:
        - name: name
          in: query
          required: true
          description: ENS name to check (without .eth suffix)
          schema:
            type: string
            example: vitalik
      responses:
        '200':
          description: ENS availability result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ENSAvailabilityResponse'
        '400':
          description: Invalid ENS name
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/ens/metadata:
    get:
      operationId: getENSMetadata
      summary: Get ENS name metadata
      description: |
        Get full metadata for a registered ENS name including Ethereum address,
        avatar, social links, and other text records.
      parameters:
        - name: name
          in: query
          required: true
          description: ENS name to look up (without .eth suffix)
          schema:
            type: string
            example: vitalik
      responses:
        '200':
          description: ENS metadata
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ENSMetadataResponse'
        '400':
          description: Invalid ENS name
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: ENS name not registered
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/ens/health:
    get:
      operationId: ensHealthCheck
      summary: ENS service health check
      description: Check if the ENS service is operational and the Ethereum RPC connection is healthy.
      responses:
        '200':
          description: ENS service is healthy
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ENSHealthResponse'

  /health:
    get:
      operationId: healthCheck
      summary: API health check
      description: Check if the API is operational and get basic status information.
      responses:
        '200':
          description: API is healthy
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthResponse'

components:
  schemas:
    CheckResponse:
      type: object
      description: Response when checking a single TLD
      required:
        - name
        - results
        - totalMs
        - timestamp
      properties:
        name:
          type: string
          description: The domain name that was checked (without TLD)
          example: mycoolstartup
        results:
          type: array
          items:
            $ref: '#/components/schemas/DomainResult'
        totalMs:
          type: integer
          description: Total time to check all domains in milliseconds
          example: 250
        timestamp:
          type: string
          format: date-time
          description: ISO 8601 timestamp when the check was performed
          example: "2025-02-10T12:00:00Z"

    BulkCheckResponse:
      type: object
      description: Response when checking 2+ TLDs (includes summary counts)
      required:
        - name
        - results
        - checked
        - available
        - unavailable
        - errors
        - totalMs
        - timestamp
      properties:
        name:
          type: string
          description: The domain name that was checked (without TLD)
          example: mycoolstartup
        results:
          type: array
          items:
            $ref: '#/components/schemas/DomainResult'
        checked:
          type: integer
          description: Total number of TLDs checked
          example: 4
        available:
          type: integer
          description: Count of available domains
          example: 2
        unavailable:
          type: integer
          description: Count of unavailable domains
          example: 1
        errors:
          type: integer
          description: Count of TLDs that had check errors
          example: 1
        totalMs:
          type: integer
          description: Total time to check all domains in milliseconds
          example: 320
        timestamp:
          type: string
          format: date-time
          description: ISO 8601 timestamp when the check was performed
          example: "2025-02-10T12:00:00Z"

    DomainResult:
      type: object
      required:
        - domain
        - tld
        - available
        - status
        - premium
        - source
        - checkedAt
        - responseMs
      properties:
        domain:
          type: string
          description: Full domain name checked
          example: mycoolstartup.com
        tld:
          type: string
          description: Top-level domain
          example: com
        available:
          type: boolean
          description: Whether the domain is available for registration
          example: true
        status:
          type: array
          items:
            type: string
            enum: [unknown, undelegated, inactive, active, premium]
          description: Array of status strings
          example: ["undelegated", "inactive"]
        premium:
          type: boolean
          description: Whether this is a premium-priced domain
          example: false
        source:
          type: string
          description: How availability was determined
          enum: [dns, rdap, dns+cache, rdap+cache]
          example: rdap
        checkedAt:
          type: string
          format: date-time
          description: ISO 8601 timestamp of this specific check
          example: "2025-02-10T12:00:00Z"
        responseMs:
          type: integer
          description: Response time for this check in milliseconds
          example: 180
        error:
          type: string
          description: Error message if the check failed (omitted on success)
          example: rate_limited

    TLDsResponse:
      type: object
      required:
        - total
      properties:
        total:
          type: integer
          description: Total number of TLDs returned
          example: 511
        categories:
          type: array
          description: List of category objects (default and category filter responses)
          items:
            $ref: '#/components/schemas/Category'
        tlds:
          type: array
          description: Flat list of TLD info objects (type filter response)
          items:
            $ref: '#/components/schemas/TLDInfo'
        all:
          type: array
          description: All TLD strings sorted alphabetically (default response only)
          items:
            type: string
          example: ["academy", "accountant", "ai", "app", "com"]

    Category:
      type: object
      required:
        - name
        - label
        - description
        - count
        - tlds
      properties:
        name:
          type: string
          description: Category identifier
          example: technology
        label:
          type: string
          description: Display label
          example: Technology
        description:
          type: string
          description: Category description
          example: Technology, software, and IT
        count:
          type: integer
          description: Number of TLDs in the category
          example: 21
        tlds:
          type: array
          items:
            type: string
          description: List of TLD strings in this category
          example: ["dev", "app", "tech", "io", "ai"]

    TLDInfo:
      type: object
      required:
        - tld
        - type
        - enabled
      properties:
        tld:
          type: string
          description: The TLD extension
          example: com
        type:
          type: string
          enum: [gTLD, ccTLD]
          description: Type of TLD
          example: gTLD
        rdapServer:
          type: string
          description: RDAP server used for availability checks
          example: rdap.verisign.com/com/v1
        whoisServer:
          type: string
          description: WHOIS server (if applicable)
        categories:
          type: array
          items:
            type: string
          description: Categories this TLD belongs to
          example: ["top20", "technology"]
        enabled:
          type: boolean
          description: Whether the TLD is currently enabled
          example: true

    RegisterResponse:
      type: object
      required:
        - domain
        - registrars
        - timestamp
      properties:
        domain:
          type: string
          example: mycoolstartup.com
        registrars:
          type: array
          items:
            $ref: '#/components/schemas/RegistrarInfo'
        timestamp:
          type: string
          format: date-time
          description: ISO 8601 timestamp of the response
          example: "2025-02-10T12:00:00Z"

    RegistrarInfo:
      type: object
      required:
        - name
        - slug
        - url
      properties:
        name:
          type: string
          description: Registrar display name
          example: Porkbun
        slug:
          type: string
          description: Registrar identifier
          example: porkbun
        url:
          type: string
          format: uri
          description: Direct link to register
          example: https://porkbun.com/checkout/search?q=mycoolstartup.com
        estimatedPrice:
          type: number
          description: Estimated price in USD (Porkbun only, for supported TLDs)
          example: 9.73

    HealthResponse:
      type: object
      required:
        - status
        - version
        - tlds
        - cacheStats
      properties:
        status:
          type: string
          description: API status
          example: ok
        version:
          type: string
          description: API version
          example: "0.3.0"
        tlds:
          type: integer
          description: Number of supported TLDs
          example: 511
        cacheStats:
          type: object
          properties:
            size:
              type: integer
              description: Number of cached domain results
              example: 42

    ENSAvailabilityResponse:
      type: object
      required:
        - name
        - available
        - responseMs
        - source
        - checkedAt
      properties:
        name:
          type: string
          description: Full ENS name with .eth suffix
          example: vitalik.eth
        available:
          type: boolean
          description: Whether the name is available for registration
          example: false
        owner:
          type: string
          description: Ethereum address of current owner (only if taken)
          example: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
        resolver:
          type: string
          description: Resolver contract address (only if taken)
          example: "0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63"
        registrationPrice:
          $ref: '#/components/schemas/RegistrationPrice'
        responseMs:
          type: integer
          description: Response time in milliseconds
          example: 450
        source:
          type: string
          description: Data source
          enum: [rpc, rpc+cache]
          example: rpc
        checkedAt:
          type: string
          format: date-time
          example: "2025-02-10T12:00:00Z"

    RegistrationPrice:
      type: object
      description: ENS registration cost (only included when name is available)
      properties:
        wei:
          type: string
          description: Annual cost in wei
          example: "158548959918"
        eth:
          type: string
          description: Annual cost in ETH
          example: "0.000000158548959918"
        usdEstimate:
          type: number
          description: Estimated annual cost in USD
          example: 5.00

    ENSMetadataResponse:
      type: object
      required:
        - name
        - owner
        - responseMs
        - source
        - checkedAt
      properties:
        name:
          type: string
          description: Full ENS name
          example: vitalik.eth
        owner:
          type: string
          description: Ethereum address of the owner
          example: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
        resolver:
          type: string
          description: Resolver contract address
        address:
          type: string
          description: ETH address the name resolves to
        records:
          type: object
          properties:
            avatar:
              type: string
              description: Avatar (EIP-155 or URL)
            url:
              type: string
              description: Website URL
            description:
              type: string
              description: Description text
            twitter:
              type: string
              description: Twitter/X handle
            github:
              type: string
              description: GitHub username
            email:
              type: string
              description: Email address
            contenthash:
              type: string
              description: Content hash (IPFS/Swarm)
        responseMs:
          type: integer
          description: Response time in milliseconds
          example: 1200
        source:
          type: string
          enum: [rpc, rpc+cache]
          example: rpc
        checkedAt:
          type: string
          format: date-time

    ENSHealthResponse:
      type: object
      properties:
        status:
          type: string
          description: Service status (ok or degraded)
          example: ok
        service:
          type: string
          example: robotdomainsearch-ens
        ens:
          type: object
          properties:
            status:
              type: string
            rpcConnected:
              type: boolean
        cacheStats:
          type: object
          properties:
            availability:
              type: integer
            metadata:
              type: integer

    AftermarketResponse:
      type: object
      required:
        - domain
        - listed
        - listings
        - errors
        - meta
      properties:
        domain:
          type: string
          description: The queried domain name (lowercased)
          example: premium.com
        timestamp:
          type: string
          format: date-time
          description: When the response was generated
        listed:
          type: boolean
          description: True if the domain is listed on any source
          example: true
        summary:
          $ref: '#/components/schemas/AftermarketSummary'
        listings:
          type: array
          items:
            $ref: '#/components/schemas/AftermarketListing'
        errors:
          type: array
          items:
            $ref: '#/components/schemas/AftermarketError'
        meta:
          $ref: '#/components/schemas/AftermarketMeta'

    AftermarketSummary:
      type: object
      properties:
        totalSources:
          type: integer
          description: Total registered providers
          example: 2
        sourcesChecked:
          type: integer
          description: Providers queried (including errored)
          example: 2
        sourcesWithData:
          type: integer
          description: Providers that returned valid data
          example: 2
        listedCount:
          type: integer
          description: How many sources have the domain listed
          example: 1
        lowestPrice:
          type: object
          nullable: true
          description: Cheapest listing across all sources
          properties:
            amount:
              type: number
              example: 2500.00
            currency:
              type: string
              example: USD
            source:
              type: string
              example: dynadot
            saleType:
              type: string
              example: buyNow
        hasAuction:
          type: boolean
          example: false
        hasMakeOffer:
          type: boolean
          example: false
        hasBackorder:
          type: boolean
          example: false

    AftermarketListing:
      type: object
      required:
        - source
        - platform
        - status
      properties:
        source:
          type: string
          description: Provider identifier
          example: sedo
        platform:
          type: string
          description: Human-readable provider name
          example: Sedo
        status:
          type: string
          enum: [listed, notListed, auction, backorder, error]
          description: Listing status on this source
          example: listed
        saleType:
          type: string
          enum: [buyNow, makeOffer, auction, backorder]
          description: Type of sale
          example: buyNow
        price:
          type: object
          nullable: true
          description: Listing price (null if make-offer only)
          properties:
            amount:
              type: number
              example: 2700.00
            currency:
              type: string
              example: USD
        makeOffer:
          type: boolean
          description: Whether the seller accepts offers
        auction:
          type: boolean
          description: Whether the domain is in an active auction
        url:
          type: string
          format: uri
          description: Direct link to the listing page
        affiliateUrl:
          type: string
          format: uri
          description: Affiliate/partner link
        lastChecked:
          type: string
          format: date-time
          description: When this source was queried
        responseMs:
          type: number
          description: Source response time in milliseconds
          example: 450

    AftermarketError:
      type: object
      required:
        - source
        - code
        - message
        - retryable
      properties:
        source:
          type: string
          description: Which provider errored
          example: sedo
        code:
          type: string
          description: Error code
          enum: [not_configured, timeout, rate_limited, auth_error, unavailable]
          example: timeout
        message:
          type: string
          description: Human-readable error description
          example: "sedo: request failed: context deadline exceeded"
        retryable:
          type: boolean
          description: Whether the request can be retried
          example: true

    AftermarketMeta:
      type: object
      properties:
        totalMs:
          type: number
          description: Total response time in milliseconds
          example: 455
        affiliateDisclosure:
          type: string
          description: Disclosure about affiliate links
          example: "Links may earn RobotDomainSearch a commission at no extra cost to you."
        cacheHit:
          type: boolean
          description: Whether the response was served from cache
          example: false
        cacheTTL:
          type: number
          description: Cache TTL in seconds for this response
          example: 900

    NameSearchPresenceResponse:
      type: object
      required:
        - name
        - score
        - status
        - summary
        - engines
        - signals
        - errors
        - total_ms
        - timestamp
        - cache_hit
      properties:
        name:
          type: string
          description: The name that was searched
          example: mycoolstartup
        score:
          type: integer
          description: Overall presence score (0–100)
          example: 7
        status:
          type: string
          enum: [clean, low, medium, high]
          description: "Presence level: clean (0–10), low (11–30), medium (31–60), high (61–100)"
          example: clean
        summary:
          type: string
          description: AI-generated summary of the name's online presence
          example: "No significant online presence exists for this name..."
        engines:
          type: array
          items:
            $ref: '#/components/schemas/PresenceEngine'
        signals:
          $ref: '#/components/schemas/PresenceSignals'
        errors:
          type: array
          items:
            $ref: '#/components/schemas/PresenceError'
        total_ms:
          type: integer
          description: Total response time in milliseconds
          example: 2642
        timestamp:
          type: string
          format: date-time
          description: When the response was generated
          example: "2026-02-17T14:00:20Z"
        cache_hit:
          type: boolean
          description: Whether the response was served from cache
          example: false

    PresenceEngine:
      type: object
      required:
        - engine
        - score
        - exact_hits
        - loose_hits
        - total_results_estimate
        - top_matches
        - response_ms
      properties:
        engine:
          type: string
          description: Search engine identifier
          enum: [brave, perplexity]
          example: brave
        score:
          type: integer
          description: Per-engine presence score (0–100)
          example: 45
        exact_hits:
          type: integer
          description: Number of results with an exact name match
          example: 3
        loose_hits:
          type: integer
          description: Number of results with a partial/related match
          example: 7
        total_results_estimate:
          type: integer
          description: Estimated total results from this engine
          example: 10
        top_matches:
          type: array
          items:
            $ref: '#/components/schemas/PresenceMatch'
        response_ms:
          type: integer
          description: Engine response time in milliseconds
          example: 518

    PresenceMatch:
      type: object
      required:
        - title
        - url
        - type
        - relevance
      properties:
        title:
          type: string
          description: Page title of the result
          example: "Example - Wikipedia"
        url:
          type: string
          format: uri
          description: URL of the result
          example: "https://en.wikipedia.org/wiki/Example"
        type:
          type: string
          description: Result type
          enum: [domain, company, product, brand]
          example: company
        relevance:
          type: string
          description: Relevance level
          enum: [high, medium, low]
          example: high

    PresenceSignals:
      type: object
      properties:
        exact_phrase_found:
          type: boolean
          description: Whether the exact name appears in search results
          example: false
        brand_exists:
          type: boolean
          description: Whether an existing brand uses this name
          example: false
        company_exists:
          type: boolean
          description: Whether an existing company uses this name
          example: false
        product_exists:
          type: boolean
          description: Whether an existing product uses this name
          example: false
        domain_registered:
          type: boolean
          description: Whether a matching domain appears to be registered
          example: false
        social_handles_found:
          type: array
          items:
            type: string
          description: Social media handles found (if any)
          example: []
        notable_individuals:
          type: array
          items:
            type: string
          description: Notable individuals associated with this name (if any)
          example: []

    PresenceError:
      type: object
      properties:
        engine:
          type: string
          description: Which engine errored
          example: perplexity
        message:
          type: string
          description: Error description
          example: "request timeout"

    Error:
      type: object
      required:
        - error
        - message
      properties:
        error:
          type: string
          description: Error code
          example: invalid_name
        message:
          type: string
          description: Human-readable error message
          example: Name must be 1-63 characters, alphanumeric with hyphens

# No authentication required
