openapi: 3.1.0
info:
  title: RankParse API
  version: 1.0.0
  description: >
    SEO data API with 22+ endpoints. Backlinks, domain authority, tech stack,
    page metadata, and more for any domain. Starting at $0.003 per request.
  contact:
    name: RankParse Support
    url: https://rankparse.com
  license:
    name: Proprietary
    identifier: LicenseRef-scancode-proprietary-license

servers:
  - url: https://api.rankparse.com
    description: Production

security:
  - ApiKeyAuth: []

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key

  parameters:
    domain:
      name: domain
      in: query
      required: true
      schema:
        type: string
      description: The domain to query (e.g. "example.com")
    limit:
      name: limit
      in: query
      required: false
      schema:
        type: integer
        default: 100
        minimum: 1
        maximum: 1000
      description: Maximum number of results to return (default 100, max 1000)
    offset:
      name: offset
      in: query
      required: false
      schema:
        type: integer
        default: 0
        minimum: 0
      description: Number of results to skip for pagination

  schemas:
    Error:
      type: object
      required: [error, code, message]
      properties:
        error:
          type: string
        code:
          type: string
        message:
          type: string

    EnvelopeFields:
      type: object
      required: [credits_used, credits_remaining, crawl_release, cached]
      properties:
        domain:
          type: string
        url:
          type: string
        total:
          type: integer
        limit:
          type: integer
        offset:
          type: integer
        credits_used:
          type: integer
          minimum: 0
        credits_remaining:
          type: integer
          minimum: 0
        crawl_release:
          type: string
        cached:
          type: boolean

    BacklinkRow:
      type: object
      required: [from_domain, from_url, to_url, link_type, domain_host_count, crawled_at]
      properties:
        from_domain:
          type: string
        from_url:
          type: string
        to_url:
          type: string
        anchor_text:
          type: ['string', 'null']
        rel:
          type: ['string', 'null']
        link_type:
          type: string
        domain_host_count:
          type: number
          minimum: 0
        crawled_at:
          type: string

    ReferringDomainRow:
      type: object
      required: [from_domain, dofollow_links, nofollow_links, total_links]
      properties:
        from_domain:
          type: string
        dofollow_links:
          type: integer
          minimum: 0
        nofollow_links:
          type: integer
          minimum: 0
        total_links:
          type: integer
          minimum: 0

    OutboundLinkRow:
      type: object
      required: [to_domain, to_url, link_type, edge_count]
      properties:
        to_domain:
          type: string
        to_url:
          type: string
        anchor_text:
          type: ['string', 'null']
        link_type:
          type: string
        edge_count:
          type: integer
          minimum: 1

    AnchorTextRow:
      type: object
      required: [anchor_text, link_count, domain_count]
      properties:
        anchor_text:
          type: string
        link_count:
          type: integer
          minimum: 1
        domain_count:
          type: integer
          minimum: 1

    TopPageRow:
      type: object
      required: [url, inbound_links, referring_domains]
      properties:
        url:
          type: string
        inbound_links:
          type: integer
          minimum: 1
        referring_domains:
          type: integer
          minimum: 1
        status_code:
          type: ['integer', 'null']
        mime:
          type: ['string', 'null']

    DomainAuthority:
      type: object
      required: [score, referring_domains, total_host_count]
      properties:
        score:
          type: integer
          minimum: 0
          maximum: 100
        referring_domains:
          type: integer
          minimum: 0
        total_host_count:
          type: number
          minimum: 0

    DomainRank:
      type: object
      required: [inbound_edges, unique_domains, avg_linking_host_count]
      properties:
        inbound_edges:
          type: integer
          minimum: 0
        unique_domains:
          type: integer
          minimum: 0
        avg_linking_host_count:
          type: number
          minimum: 0

    CrawlHistory:
      type: object
      required: [total_urls]
      properties:
        first_seen:
          type: ['string', 'null']
        last_seen:
          type: ['string', 'null']
        total_urls:
          type: integer
          minimum: 0

    UrlIndexRow:
      type: object
      required: [url, status_code, mime, crawled_at]
      properties:
        url:
          type: string
        status_code:
          type: integer
        mime:
          type: string
        crawled_at:
          type: string

    PageMeta:
      type: ['object', 'null']
      required: [url]
      properties:
        url:
          type: string
        title:
          type: ['string', 'null']
        description:
          type: ['string', 'null']
        h1:
          type: ['string', 'null']
        canonical:
          type: ['string', 'null']

    TechStack:
      type: object
      properties:
        server:
          type: ['string', 'null']
        x_powered_by:
          type: ['string', 'null']
        generator:
          type: ['string', 'null']

    StatusCodeCount:
      type: object
      required: [status_code, count]
      properties:
        status_code:
          type: integer
        count:
          type: integer
          minimum: 1

    ContentTypeCount:
      type: object
      required: [mime, count]
      properties:
        mime:
          type: string
        count:
          type: integer
          minimum: 1

    LanguageCount:
      type: object
      required: [lang, page_count]
      properties:
        lang:
          type: string
        page_count:
          type: integer
          minimum: 1

    DomainOverlapRow:
      type: object
      required: [from_domain, total_links, targets_linked]
      properties:
        from_domain:
          type: string
        total_links:
          type: number
          minimum: 0
        targets_linked:
          type: integer
          minimum: 1

    LinkIntersectRow:
      type: object
      required: [from_domain, total_links]
      properties:
        from_domain:
          type: string
        total_links:
          type: number
          minimum: 0

    SimilarDomainRow:
      type: object
      required: [similar_domain, shared_linkers]
      properties:
        similar_domain:
          type: string
        shared_linkers:
          type: integer
          minimum: 1

    SiteExplorer:
      type: object
      required: [backlinks, backlinks_total, authority, top_pages, anchor_text]
      properties:
        backlinks:
          type: array
          items:
            $ref: '#/components/schemas/BacklinkRow'
        backlinks_total:
          type: integer
          minimum: 0
        authority:
          $ref: '#/components/schemas/DomainAuthority'
        top_pages:
          type: array
          items:
            $ref: '#/components/schemas/TopPageRow'
        anchor_text:
          type: array
          items:
            $ref: '#/components/schemas/AnchorTextRow'

    BatchResultItem:
      type: object
      required: [domain, success]
      properties:
        domain:
          type: string
        data:
          type: array
          items:
            $ref: '#/components/schemas/BacklinkRow'
        total:
          type: integer
        success:
          type: boolean
        error:
          type: string

    StubData:
      type: object
      required: [status, reason]
      properties:
        status:
          type: string
          enum: ['not_yet_available']
        reason:
          type: string

    LayerStatus:
      type: object
      required: [ok]
      properties:
        ok:
          type: boolean
        latency_ms:
          type: number
        detail:
          type: string
        error:
          type: string

    HealthResponse:
      type: object
      required: [overall, timestamp, crawl_release, d1, r2, r2sql]
      properties:
        overall:
          type: string
          enum: ['healthy', 'degraded', 'down']
        timestamp:
          type: string
        crawl_release:
          type: string
        d1:
          $ref: '#/components/schemas/LayerStatus'
        r2:
          $ref: '#/components/schemas/LayerStatus'
        r2sql:
          $ref: '#/components/schemas/LayerStatus'

  responses:
    BadRequest:
      description: Invalid request parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    PaymentRequired:
      description: Insufficient credits
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: Rate limit exceeded (60 requests/minute)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

paths:
  /health:
    get:
      operationId: getHealth
      summary: Health check
      description: Returns the health status of all subsystems (D1, R2, R2 SQL). No authentication required.
      security: []
      tags: [System]
      responses:
        '200':
          description: All systems healthy
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthResponse'
        '207':
          description: Degraded — some subsystems unhealthy
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthResponse'
        '404':
          description: Not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: Down — critical subsystems unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthResponse'

  /v1/credits:
    get:
      operationId: getCredits
      summary: Check credit balance
      description: Returns the current credit balance for the authenticated user. Does not deduct credits.
      tags: [Account]
      responses:
        '200':
          description: Current credit balance
          content:
            application/json:
              schema:
                type: object
                required: [credits]
                properties:
                  credits:
                    type: integer
                    minimum: 0
        '401':
          $ref: '#/components/responses/Unauthorized'

  /v1/backlinks:
    get:
      operationId: getBacklinks
      summary: Get backlinks for a domain
      description: Returns inbound links pointing to the specified domain. Costs 2 credits.
      tags: [Link Graph]
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
      responses:
        '200':
          description: Backlinks for the domain
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/BacklinkRow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/referring-domains:
    get:
      operationId: getReferringDomains
      summary: Get referring domains
      description: Returns domains that link to the specified domain with link counts. Costs 2 credits.
      tags: [Link Graph]
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
      responses:
        '200':
          description: Referring domains
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/ReferringDomainRow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/outbound-links:
    get:
      operationId: getOutboundLinks
      summary: Get outbound links from a domain
      description: Returns links going out from the specified domain. Costs 2 credits.
      tags: [Link Graph]
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
      responses:
        '200':
          description: Outbound links
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/OutboundLinkRow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/anchor-text:
    get:
      operationId: getAnchorText
      summary: Get anchor text distribution
      description: Returns anchor text phrases used in links pointing to the domain. Costs 2 credits.
      tags: [Link Graph]
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
      responses:
        '200':
          description: Anchor text distribution
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/AnchorTextRow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/top-pages:
    get:
      operationId: getTopPages
      summary: Get top pages by inbound links
      description: Returns pages on the domain ranked by number of inbound links. Costs 2 credits.
      tags: [Link Graph]
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
      responses:
        '200':
          description: Top pages
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/TopPageRow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/url-index:
    get:
      operationId: getUrlIndex
      summary: Get URL index (CDX)
      description: Returns crawled URLs for a domain with status codes and MIME types. Costs 2 credits.
      tags: [URL Index]
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
      responses:
        '200':
          description: URL index entries
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/UrlIndexRow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/domain-authority:
    get:
      operationId: getDomainAuthority
      summary: Get domain authority score
      description: Returns a 0-100 authority score based on referring domains. Costs 1 credit.
      tags: [Domain Metrics]
      parameters:
        - $ref: '#/components/parameters/domain'
      responses:
        '200':
          description: Domain authority data
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        $ref: '#/components/schemas/DomainAuthority'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/domain-rank:
    get:
      operationId: getDomainRank
      summary: Get domain rank metrics
      description: Returns inbound edge count, unique linking domains, and average host count. Costs 2 credits.
      tags: [Domain Metrics]
      parameters:
        - $ref: '#/components/parameters/domain'
      responses:
        '200':
          description: Domain rank data
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        $ref: '#/components/schemas/DomainRank'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/crawl-history:
    get:
      operationId: getCrawlHistory
      summary: Get crawl history for a domain
      description: Returns first/last seen dates and total URL count from the crawl index. Costs 2 credits.
      tags: [URL Index]
      parameters:
        - $ref: '#/components/parameters/domain'
      responses:
        '200':
          description: Crawl history
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        $ref: '#/components/schemas/CrawlHistory'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/page-meta:
    get:
      operationId: getPageMeta
      summary: Get page metadata
      description: >
        Returns title, description, h1, and canonical URL for a specific page.
        Returns null data (not 404) when the URL is not found. Costs 2 credits.
      tags: [Page Metadata]
      parameters:
        - name: url
          in: query
          required: true
          schema:
            type: string
          description: The full URL to look up (e.g. "https://example.com/page")
      responses:
        '200':
          description: Page metadata (data may be null if URL not found)
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        $ref: '#/components/schemas/PageMeta'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/tech-stack:
    get:
      operationId: getTechStack
      summary: Get detected tech stack
      description: Returns server, X-Powered-By, and generator meta tag for a domain. Costs 2 credits.
      tags: [Page Metadata]
      parameters:
        - $ref: '#/components/parameters/domain'
      responses:
        '200':
          description: Tech stack data
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        $ref: '#/components/schemas/TechStack'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/status-codes:
    get:
      operationId: getStatusCodes
      summary: Get HTTP status code distribution
      description: Returns a count of URLs by HTTP status code for the domain. Costs 2 credits.
      tags: [URL Index]
      parameters:
        - $ref: '#/components/parameters/domain'
      responses:
        '200':
          description: Status code counts
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/StatusCodeCount'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/content-types:
    get:
      operationId: getContentTypes
      summary: Get content type distribution
      description: Returns a count of URLs by MIME type for the domain. Costs 2 credits.
      tags: [URL Index]
      parameters:
        - $ref: '#/components/parameters/domain'
      responses:
        '200':
          description: Content type counts
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/ContentTypeCount'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/language:
    get:
      operationId: getLanguage
      summary: Get language distribution
      description: Returns page count by detected language for the domain (max 5 results). Costs 2 credits.
      tags: [Page Metadata]
      parameters:
        - $ref: '#/components/parameters/domain'
      responses:
        '200':
          description: Language distribution
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        maxItems: 5
                        items:
                          $ref: '#/components/schemas/LanguageCount'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/domain-overlap:
    get:
      operationId: getDomainOverlap
      summary: Find domains linking to multiple targets
      description: >
        Returns domains that link to two or more of the specified target domains.
        Requires at least 2 domains. Costs 5 credits.
      tags: [Cross-Domain]
      parameters:
        - name: domains
          in: query
          required: true
          schema:
            type: string
          description: Comma-separated list of domains (minimum 2)
        - $ref: '#/components/parameters/limit'
      responses:
        '200':
          description: Overlapping domains
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/DomainOverlapRow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/link-intersect:
    get:
      operationId: getLinkIntersect
      summary: Find domains linking to both targets
      description: Returns domains that link to both domain_a and domain_b. Costs 5 credits.
      tags: [Cross-Domain]
      parameters:
        - name: domain_a
          in: query
          required: true
          schema:
            type: string
          description: First domain to compare
        - name: domain_b
          in: query
          required: true
          schema:
            type: string
          description: Second domain to compare
        - $ref: '#/components/parameters/limit'
      responses:
        '200':
          description: Intersecting linker domains
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/LinkIntersectRow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/similar-domains:
    get:
      operationId: getSimilarDomains
      summary: Find similar domains
      description: >
        Returns domains that share linking domains with the target.
        Limit is capped at 100 (not 1000). Costs 5 credits.
      tags: [Cross-Domain]
      parameters:
        - $ref: '#/components/parameters/domain'
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 100
            minimum: 1
            maximum: 100
          description: Maximum results (default 100, max 100)
      responses:
        '200':
          description: Similar domains
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/SimilarDomainRow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/site-explorer:
    get:
      operationId: getSiteExplorer
      summary: Full site overview
      description: >
        Returns backlinks, authority score, top pages, and anchor text in a single request.
        Costs 10 credits.
      tags: [Power Endpoints]
      parameters:
        - $ref: '#/components/parameters/domain'
      responses:
        '200':
          description: Site explorer data
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        $ref: '#/components/schemas/SiteExplorer'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/batch:
    post:
      operationId: postBatch
      summary: Batch backlink lookup
      description: >
        Looks up backlinks for up to 50 domains in a single request.
        Costs 2 credits per successfully queried domain (charged after queries complete).
      tags: [Power Endpoints]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [domains]
              properties:
                domains:
                  type: array
                  items:
                    type: string
                  minItems: 1
                  maxItems: 50
                  description: Domains to look up backlinks for
      responses:
        '200':
          description: Batch results
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/BatchResultItem'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/link-velocity:
    get:
      operationId: getLinkVelocity
      summary: Link velocity (stub)
      description: >
        Not yet available in v1. Requires two crawl releases to compute.
        Returns immediately with status "not_yet_available". Costs 0 credits.
      tags: [Stubs]
      parameters:
        - name: domain
          in: query
          required: false
          schema:
            type: string
          description: Domain (optional for stub endpoints)
      responses:
        '200':
          description: Stub response
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        $ref: '#/components/schemas/StubData'
                      status:
                        type: string
                        enum: ['not_yet_available']
                      reason:
                        type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/new-links:
    get:
      operationId: getNewLinks
      summary: New links (stub)
      description: >
        Not yet available in v1. Requires two crawl releases to compute.
        Returns immediately with status "not_yet_available". Costs 0 credits.
      tags: [Stubs]
      parameters:
        - name: domain
          in: query
          required: false
          schema:
            type: string
          description: Domain (optional for stub endpoints)
      responses:
        '200':
          description: Stub response
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        $ref: '#/components/schemas/StubData'
                      status:
                        type: string
                        enum: ['not_yet_available']
                      reason:
                        type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/lost-links:
    get:
      operationId: getLostLinks
      summary: Lost links (stub)
      description: >
        Not yet available in v1. Requires two crawl releases to compute.
        Returns immediately with status "not_yet_available". Costs 0 credits.
      tags: [Stubs]
      parameters:
        - name: domain
          in: query
          required: false
          schema:
            type: string
          description: Domain (optional for stub endpoints)
      responses:
        '200':
          description: Stub response
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        $ref: '#/components/schemas/StubData'
                      status:
                        type: string
                        enum: ['not_yet_available']
                      reason:
                        type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/schema-markup:
    get:
      operationId: getSchemaMarkup
      summary: Schema markup (stub)
      description: >
        Not yet available in v1. Returns immediately with status "not_yet_available". Costs 0 credits.
      tags: [Stubs]
      parameters:
        - name: url
          in: query
          required: true
          schema:
            type: string
          description: The URL to check for schema markup
      responses:
        '200':
          description: Stub response
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        $ref: '#/components/schemas/StubData'
                      status:
                        type: string
                        enum: ['not_yet_available']
                      reason:
                        type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/internal-links:
    get:
      operationId: getInternalLinks
      summary: Internal links (stub)
      description: >
        Not yet available in v1. Returns immediately with status "not_yet_available". Costs 0 credits.
      tags: [Stubs]
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
      responses:
        '200':
          description: Stub response
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/EnvelopeFields'
                  - type: object
                    required: [data]
                    properties:
                      data:
                        $ref: '#/components/schemas/StubData'
                      status:
                        type: string
                        enum: ['not_yet_available']
                      reason:
                        type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
