openapi: 3.1.0
info:
  title: FairCrawl API
  version: 1.0.0
  description: Pay-per-use web data extraction, search, enrichment, monitoring, and agent workflows. Route
    inventory is generated from the Fastify registrations; core schemas and examples were verified against the
    production surface on 2026-08-06.
servers:
  - url: https://api.faircompany.ai
    description: Production
  - url: https://staging.api.faircompany.ai
    description: Staging
security:
  - BearerAuth: []
tags:
  - name: Web data
  - name: FairCrawl
  - name: Agent
  - name: Agent campaigns
  - name: Enrichment
  - name: Monitors
  - name: Watches
  - name: Freshness
  - name: Publishers
x-generated-at: 2026-08-06
x-generated-from:
  - apps/api/src/crawl/routes.ts
  - apps/api/src/crawl/campaign-routes.ts
  - apps/api/src/crawl/watch-routes.ts
  - apps/api/src/crawl/monitor-routes.ts
  - apps/api/src/crawl/freshness/routes.ts
x-production-evidence: .forge/workflows/evidence/PRD-354/faircrawl-prod
x-operation-count: 103
paths:
  /v1/crawl/{platform}/{action}:
    get:
      operationId: getCrawlPlatformAction
      summary: GET /v1/crawl/{platform}/{action}
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: platform
          in: path
          required: true
          schema:
            type: string
        - name: action
          in: path
          required: true
          schema:
            type: string
    post:
      operationId: postCrawlPlatformAction
      summary: POST /v1/crawl/{platform}/{action}
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: platform
          in: path
          required: true
          schema:
            type: string
        - name: action
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/activity:
    get:
      operationId: getCrawlActivity
      summary: Read recent org-scoped crawl activity
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/agent:
    post:
      operationId: postCrawlAgent
      summary: Plan a natural-language crawl job
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AgentRequest"
  /v1/crawl/agent/{request_id}/cancel:
    post:
      operationId: postCrawlAgentRequestIdCancel
      summary: Cancel an agent run
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: request_id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/agent/{request_id}/confirm:
    post:
      operationId: postCrawlAgentRequestIdConfirm
      summary: Confirm and execute an agent plan
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: request_id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/agent/{request_id}/status:
    get:
      operationId: getCrawlAgentRequestIdStatus
      summary: Read or wait for agent status
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: request_id
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/agent/campaigns:
    get:
      operationId: getCrawlAgentCampaigns
      summary: GET /v1/crawl/agent/campaigns
      tags:
        - Agent campaigns
      x-source: apps/api/src/crawl/campaign-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
    post:
      operationId: postCrawlAgentCampaigns
      summary: POST /v1/crawl/agent/campaigns
      tags:
        - Agent campaigns
      x-source: apps/api/src/crawl/campaign-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/agent/campaigns/{id}:
    get:
      operationId: getCrawlAgentCampaignsId
      summary: GET /v1/crawl/agent/campaigns/{id}
      tags:
        - Agent campaigns
      x-source: apps/api/src/crawl/campaign-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
    patch:
      operationId: patchCrawlAgentCampaignsId
      summary: PATCH /v1/crawl/agent/campaigns/{id}
      tags:
        - Agent campaigns
      x-source: apps/api/src/crawl/campaign-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/agent/campaigns/{id}/archive:
    post:
      operationId: postCrawlAgentCampaignsIdArchive
      summary: POST /v1/crawl/agent/campaigns/{id}/archive
      tags:
        - Agent campaigns
      x-source: apps/api/src/crawl/campaign-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/agent/campaigns/{id}/diff/{runId}:
    get:
      operationId: getCrawlAgentCampaignsIdDiffRunId
      summary: GET /v1/crawl/agent/campaigns/{id}/diff/{runId}
      tags:
        - Agent campaigns
      x-source: apps/api/src/crawl/campaign-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        - name: runId
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/agent/campaigns/{id}/pause:
    post:
      operationId: postCrawlAgentCampaignsIdPause
      summary: POST /v1/crawl/agent/campaigns/{id}/pause
      tags:
        - Agent campaigns
      x-source: apps/api/src/crawl/campaign-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/agent/campaigns/{id}/resume:
    post:
      operationId: postCrawlAgentCampaignsIdResume
      summary: POST /v1/crawl/agent/campaigns/{id}/resume
      tags:
        - Agent campaigns
      x-source: apps/api/src/crawl/campaign-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/agent/campaigns/{id}/run:
    post:
      operationId: postCrawlAgentCampaignsIdRun
      summary: POST /v1/crawl/agent/campaigns/{id}/run
      tags:
        - Agent campaigns
      x-source: apps/api/src/crawl/campaign-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/agent/campaigns/{id}/runs:
    get:
      operationId: getCrawlAgentCampaignsIdRuns
      summary: GET /v1/crawl/agent/campaigns/{id}/runs
      tags:
        - Agent campaigns
      x-source: apps/api/src/crawl/campaign-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/agent/conversations:
    get:
      operationId: getCrawlAgentConversations
      summary: GET /v1/crawl/agent/conversations
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/agent/conversations/{id}:
    delete:
      operationId: deleteCrawlAgentConversationsId
      summary: DELETE /v1/crawl/agent/conversations/{id}
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
    get:
      operationId: getCrawlAgentConversationsId
      summary: GET /v1/crawl/agent/conversations/{id}
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
    patch:
      operationId: patchCrawlAgentConversationsId
      summary: PATCH /v1/crawl/agent/conversations/{id}
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/agent/workspace-memory:
    delete:
      operationId: deleteCrawlAgentWorkspaceMemory
      summary: DELETE /v1/crawl/agent/workspace-memory
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
    get:
      operationId: getCrawlAgentWorkspaceMemory
      summary: GET /v1/crawl/agent/workspace-memory
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
    patch:
      operationId: patchCrawlAgentWorkspaceMemory
      summary: PATCH /v1/crawl/agent/workspace-memory
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/agent/workspace-memory/pending:
    get:
      operationId: getCrawlAgentWorkspaceMemoryPending
      summary: GET /v1/crawl/agent/workspace-memory/pending
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/agent/workspace-memory/pending/{id}/approve:
    post:
      operationId: postCrawlAgentWorkspaceMemoryPendingIdApprove
      summary: POST /v1/crawl/agent/workspace-memory/pending/{id}/approve
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/agent/workspace-memory/pending/{id}/reject:
    post:
      operationId: postCrawlAgentWorkspaceMemoryPendingIdReject
      summary: POST /v1/crawl/agent/workspace-memory/pending/{id}/reject
      tags:
        - Agent
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/batch:
    post:
      operationId: postCrawlBatch
      summary: POST /v1/crawl/batch
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "202":
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/batch/{id}:
    get:
      operationId: getCrawlBatchId
      summary: GET /v1/crawl/batch/{id}
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/cache:
    delete:
      operationId: deleteCrawlCache
      summary: DELETE /v1/crawl/cache
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/endpoints:
    get:
      operationId: getCrawlEndpoints
      summary: List the live endpoint and per-call price catalog
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EndpointCatalog"
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/enrich/company:
    post:
      operationId: postCrawlEnrichCompany
      summary: Enrich a company from its domain
      tags:
        - Enrichment
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/enrich/contact:
    post:
      operationId: postCrawlEnrichContact
      summary: POST /v1/crawl/enrich/contact
      tags:
        - Enrichment
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/enrich/contacts:
    post:
      operationId: postCrawlEnrichContacts
      summary: POST /v1/crawl/enrich/contacts
      tags:
        - Enrichment
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/enrich/jobs:
    get:
      operationId: getCrawlEnrichJobs
      summary: GET /v1/crawl/enrich/jobs
      tags:
        - Enrichment
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/enrich/jobs/{id}:
    get:
      operationId: getCrawlEnrichJobsId
      summary: GET /v1/crawl/enrich/jobs/{id}
      tags:
        - Enrichment
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/extract-schema:
    post:
      operationId: postCrawlExtractSchema
      summary: POST /v1/crawl/extract-schema
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/health:
    get:
      operationId: getCrawlHealth
      summary: GET /v1/crawl/health
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/health/methods:
    get:
      operationId: getCrawlHealthMethods
      summary: GET /v1/crawl/health/methods
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/history:
    get:
      operationId: getCrawlHistory
      summary: GET /v1/crawl/history
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/history/{entryType}/{id}:
    get:
      operationId: getCrawlHistoryEntryTypeId
      summary: GET /v1/crawl/history/{entryType}/{id}
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: entryType
          in: path
          required: true
          schema:
            type: string
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/interact:
    post:
      operationId: postCrawlInteract
      summary: Run ordered browser actions and extraction
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/jobs:
    get:
      operationId: getCrawlJobs
      summary: GET /v1/crawl/jobs
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/jobs/{id}:
    get:
      operationId: getCrawlJobsId
      summary: GET /v1/crawl/jobs/{id}
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/map:
    post:
      operationId: postCrawlMap
      summary: Discover URLs without scraping full content
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MapRequest"
  /v1/crawl/monitors:
    get:
      operationId: getCrawlMonitors
      summary: GET /v1/crawl/monitors
      tags:
        - Monitors
      x-source: apps/api/src/crawl/monitor-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
    post:
      operationId: postCrawlMonitors
      summary: Create a search monitor
      tags:
        - Monitors
      x-source: apps/api/src/crawl/monitor-routes.ts
      responses:
        "201":
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/monitors/{id}:
    delete:
      operationId: deleteCrawlMonitorsId
      summary: DELETE /v1/crawl/monitors/{id}
      tags:
        - Monitors
      x-source: apps/api/src/crawl/monitor-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
    get:
      operationId: getCrawlMonitorsId
      summary: GET /v1/crawl/monitors/{id}
      tags:
        - Monitors
      x-source: apps/api/src/crawl/monitor-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/monitors/{id}/alerts:
    get:
      operationId: getCrawlMonitorsIdAlerts
      summary: GET /v1/crawl/monitors/{id}/alerts
      tags:
        - Monitors
      x-source: apps/api/src/crawl/monitor-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/monitors/{id}/check:
    post:
      operationId: postCrawlMonitorsIdCheck
      summary: Run a monitor check now
      tags:
        - Monitors
      x-source: apps/api/src/crawl/monitor-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/publishers:
    get:
      operationId: getCrawlPublishers
      summary: GET /v1/crawl/publishers
      tags:
        - Publishers
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/publishers/{slug}:
    get:
      operationId: getCrawlPublishersSlug
      summary: GET /v1/crawl/publishers/{slug}
      tags:
        - Publishers
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/publishers/{slug}/reliability:
    get:
      operationId: getCrawlPublishersSlugReliability
      summary: GET /v1/crawl/publishers/{slug}/reliability
      tags:
        - Publishers
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/publishers/{slug}/subscribe:
    delete:
      operationId: deleteCrawlPublishersSlugSubscribe
      summary: DELETE /v1/crawl/publishers/{slug}/subscribe
      tags:
        - Publishers
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
    post:
      operationId: postCrawlPublishersSlugSubscribe
      summary: POST /v1/crawl/publishers/{slug}/subscribe
      tags:
        - Publishers
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/publishers/request:
    post:
      operationId: postCrawlPublishersRequest
      summary: POST /v1/crawl/publishers/request
      tags:
        - Publishers
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/publishers/subscriptions:
    get:
      operationId: getCrawlPublishersSubscriptions
      summary: GET /v1/crawl/publishers/subscriptions
      tags:
        - Publishers
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/research:
    post:
      operationId: postCrawlResearch
      summary: Run multi-source research with optional synthesis
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ResearchRequest"
  /v1/crawl/search:
    post:
      operationId: postCrawlSearch
      summary: POST /v1/crawl/search
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SearchRequest"
  /v1/crawl/status/{jobId}:
    get:
      operationId: getCrawlStatusJobId
      summary: GET /v1/crawl/status/{jobId}
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: jobId
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/status/public:
    get:
      operationId: getCrawlStatusPublic
      summary: Read the public FairCrawl status snapshot
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      security: []
  /v1/crawl/usage:
    get:
      operationId: getCrawlUsage
      summary: Read metered FairCrawl usage
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/wallet/spend:
    get:
      operationId: getCrawlWalletSpend
      summary: GET /v1/crawl/wallet/spend
      tags:
        - FairCrawl
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/crawl/web/brand:
    post:
      operationId: postCrawlWebBrand
      summary: POST /v1/crawl/web/brand
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/web/crawl:
    post:
      operationId: postCrawlWebCrawl
      summary: Start a multi-page crawl
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "202":
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CrawlRequest"
  /v1/crawl/web/crawl/{jobId}:
    get:
      operationId: getCrawlWebCrawlJobId
      summary: GET /v1/crawl/web/crawl/{jobId}
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: jobId
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/web/crawl/{jobId}/cancel:
    post:
      operationId: postCrawlWebCrawlJobIdCancel
      summary: POST /v1/crawl/web/crawl/{jobId}/cancel
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: jobId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/web/discover:
    post:
      operationId: postCrawlWebDiscover
      summary: POST /v1/crawl/web/discover
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/web/estimate:
    post:
      operationId: postCrawlWebEstimate
      summary: POST /v1/crawl/web/estimate
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/web/extract:
    post:
      operationId: postCrawlWebExtract
      summary: POST /v1/crawl/web/extract
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/web/inventory:
    post:
      operationId: postCrawlWebInventory
      summary: POST /v1/crawl/web/inventory
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/web/inventory/estimate:
    post:
      operationId: postCrawlWebInventoryEstimate
      summary: POST /v1/crawl/web/inventory/estimate
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/web/inventory/stream:
    post:
      operationId: postCrawlWebInventoryStream
      summary: POST /v1/crawl/web/inventory/stream
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/web/scrape:
    post:
      operationId: postCrawlWebScrape
      summary: Scrape one URL and return extracted content
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScrapeResponse"
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ScrapeRequest"
  /v1/crawl/web/scrape/batch:
    post:
      operationId: postCrawlWebScrapeBatch
      summary: POST /v1/crawl/web/scrape/batch
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "202":
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/crawl/web/scrape/batch/{id}:
    delete:
      operationId: deleteCrawlWebScrapeBatchId
      summary: DELETE /v1/crawl/web/scrape/batch/{id}
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
    get:
      operationId: getCrawlWebScrapeBatchId
      summary: GET /v1/crawl/web/scrape/batch/{id}
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/web/scrape/batch/{id}/items:
    get:
      operationId: getCrawlWebScrapeBatchIdItems
      summary: GET /v1/crawl/web/scrape/batch/{id}/items
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/web/scrape/batch/{id}/stream:
    get:
      operationId: getCrawlWebScrapeBatchIdStream
      summary: GET /v1/crawl/web/scrape/batch/{id}/stream
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/crawl/web/search:
    get:
      operationId: getCrawlWebSearch
      summary: GET /v1/crawl/web/search
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
    post:
      operationId: postCrawlWebSearch
      summary: Search the web and scrape successful results
      tags:
        - Web data
      x-source: apps/api/src/crawl/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SearchRequest"
  /v1/freshness/dashboard:
    get:
      operationId: getFreshnessDashboard
      summary: GET /v1/freshness/dashboard
      tags:
        - Freshness
      x-source: apps/api/src/crawl/freshness/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/freshness/due:
    get:
      operationId: getFreshnessDue
      summary: GET /v1/freshness/due
      tags:
        - Freshness
      x-source: apps/api/src/crawl/freshness/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
  /v1/freshness/entities/{entity_id}:
    get:
      operationId: getFreshnessEntitiesEntityId
      summary: Read source freshness for one entity
      tags:
        - Freshness
      x-source: apps/api/src/crawl/freshness/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: entity_id
          in: path
          required: true
          schema:
            type: string
  /v1/freshness/sources:
    post:
      operationId: postFreshnessSources
      summary: POST /v1/freshness/sources
      tags:
        - Freshness
      x-source: apps/api/src/crawl/freshness/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/freshness/sources/{id}:
    delete:
      operationId: deleteFreshnessSourcesId
      summary: DELETE /v1/freshness/sources/{id}
      tags:
        - Freshness
      x-source: apps/api/src/crawl/freshness/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/freshness/sources/{id}/fetched:
    post:
      operationId: postFreshnessSourcesIdFetched
      summary: POST /v1/freshness/sources/{id}/fetched
      tags:
        - Freshness
      x-source: apps/api/src/crawl/freshness/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/freshness/sources/bulk:
    post:
      operationId: postFreshnessSourcesBulk
      summary: POST /v1/freshness/sources/bulk
      tags:
        - Freshness
      x-source: apps/api/src/crawl/freshness/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/freshness/sources/fetched/bulk:
    post:
      operationId: postFreshnessSourcesFetchedBulk
      summary: POST /v1/freshness/sources/fetched/bulk
      tags:
        - Freshness
      x-source: apps/api/src/crawl/freshness/routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/watches:
    get:
      operationId: getWatches
      summary: GET /v1/watches
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
    post:
      operationId: postWatches
      summary: POST /v1/watches
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/watches/{id}:
    delete:
      operationId: deleteWatchesId
      summary: DELETE /v1/watches/{id}
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
    get:
      operationId: getWatchesId
      summary: GET /v1/watches/{id}
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
    patch:
      operationId: patchWatchesId
      summary: PATCH /v1/watches/{id}
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/watches/{id}/check:
    post:
      operationId: postWatchesIdCheck
      summary: POST /v1/watches/{id}/check
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/watches/{id}/diffs:
    get:
      operationId: getWatchesIdDiffs
      summary: GET /v1/watches/{id}/diffs
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/watches/{id}/latest:
    get:
      operationId: getWatchesIdLatest
      summary: GET /v1/watches/{id}/latest
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/watches/{id}/notifications:
    post:
      operationId: postWatchesIdNotifications
      summary: POST /v1/watches/{id}/notifications
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/watches/{id}/notifications/{nid}:
    delete:
      operationId: deleteWatchesIdNotificationsNid
      summary: DELETE /v1/watches/{id}/notifications/{nid}
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        - name: nid
          in: path
          required: true
          schema:
            type: string
  /v1/watches/{id}/snapshots:
    get:
      operationId: getWatchesIdSnapshots
      summary: GET /v1/watches/{id}/snapshots
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
  /v1/watches/bulk:
    post:
      operationId: postWatchesBulk
      summary: POST /v1/watches/bulk
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
  /v1/watches/bulk-check:
    post:
      operationId: postWatchesBulkCheck
      summary: POST /v1/watches/bulk-check
      tags:
        - Watches
      x-source: apps/api/src/crawl/watch-routes.ts
      responses:
        "400":
          $ref: "#/components/responses/Problem"
        "401":
          $ref: "#/components/responses/Problem"
        "402":
          $ref: "#/components/responses/Problem"
        "404":
          $ref: "#/components/responses/Problem"
        "422":
          $ref: "#/components/responses/Problem"
        "429":
          $ref: "#/components/responses/RateLimited"
        2XX:
          description: Success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
          headers:
            X-RateLimit-Limit:
              $ref: "#/components/headers/RateLimitLimit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/RateLimitRemaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/RateLimitReset"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Fair API key (fc_live_…)
  headers:
    RateLimitLimit:
      description: Requests allowed in the current minute window
      schema:
        type: integer
    RateLimitRemaining:
      description: Requests remaining in the current window
      schema:
        type: integer
    RateLimitReset:
      description: Unix timestamp when the current window resets
      schema:
        type: integer
  responses:
    Problem:
      description: RFC 9457 problem detail
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/Problem"
    RateLimited:
      description: Rate limit exceeded
      headers:
        Retry-After:
          schema:
            type: integer
        X-RateLimit-Limit:
          $ref: "#/components/headers/RateLimitLimit"
        X-RateLimit-Remaining:
          $ref: "#/components/headers/RateLimitRemaining"
        X-RateLimit-Reset:
          $ref: "#/components/headers/RateLimitReset"
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/Problem"
  schemas:
    Problem:
      type: object
      required:
        - type
        - title
        - status
        - code
        - detail
      properties:
        type:
          type: string
          format: uri
        title:
          type: string
        status:
          type: integer
        code:
          type: string
        detail:
          type: string
        requestId:
          type: string
    ScrapeRequest:
      type: object
      required:
        - url
      additionalProperties: false
      properties:
        url:
          type: string
          format: uri
        format:
          type: string
          examples:
            - markdown
        query:
          type: string
        autoConsent:
          type: boolean
          default: true
        proxy_country:
          type: string
          pattern: ^[A-Z]{2}$
        render_js:
          type: string
          enum:
            - "true"
            - "false"
        only_main_content:
          type:
            - boolean
            - string
          default: true
        screenshot:
          type: string
        prompt:
          type: string
        schema:
          type: string
        callback_url:
          type: string
        if_content_hash:
          type: string
        pdf_mode:
          type: string
          enum:
            - fast
            - auto
            - ocr
        max_pages:
          type: integer
          minimum: 1
          maximum: 200
        max_tier:
          type: string
          enum:
            - standard
            - large
        async:
          type: boolean
    ScrapeResponse:
      type: object
      required:
        - content
        - _meta
      properties:
        title:
          type:
            - string
            - "null"
        description:
          type:
            - string
            - "null"
        content:
          type: string
        html:
          type:
            - string
            - "null"
        links:
          type: array
          items:
            type: string
        metadata:
          type: object
          additionalProperties: true
        _meta:
          $ref: "#/components/schemas/BillingMeta"
    BillingMeta:
      type: object
      required:
        - requestId
        - billing_action
        - cost
        - method
        - balance
      properties:
        requestId:
          type: string
        billing_action:
          type: string
        cost:
          type: number
        method:
          type: string
        responseTimeMs:
          type: integer
        from_cache:
          type: boolean
        rate:
          type: number
        tier:
          type: string
        mtd_spend:
          type: number
        balance:
          type: number
    EndpointCatalog:
      type: object
      required:
        - platforms
        - total
        - active
      properties:
        platforms:
          type: object
          additionalProperties:
            type: array
            items:
              type: object
              additionalProperties: true
        total:
          type: integer
        active:
          type: integer
    MapRequest:
      type: object
      required:
        - url
      properties:
        url:
          type: string
          format: uri
        limit:
          type: integer
          minimum: 1
          maximum: 5000
          default: 100
        search:
          type: string
        include_subdomains:
          type: boolean
          default: false
        sitemap_only:
          type: boolean
          default: false
    SearchRequest:
      type: object
      required:
        - query
      properties:
        query:
          type: string
          minLength: 1
        limit:
          type: integer
          minimum: 1
          maximum: 20
          default: 5
        country:
          type: string
          minLength: 2
          maxLength: 2
        scrape_options:
          type: object
          additionalProperties: true
    ResearchRequest:
      type: object
      required:
        - query
      properties:
        query:
          type: string
          minLength: 1
        sources:
          type: array
          items:
            type: string
        limit:
          type: integer
          minimum: 1
          maximum: 50
          default: 10
        depth:
          type: string
          enum:
            - quick
            - default
            - deep
        synthesize:
          type: boolean
          default: true
    CrawlRequest:
      type: object
      required:
        - url
      additionalProperties: false
      properties:
        url:
          type: string
          format: uri
        limit:
          type: integer
          minimum: 1
          maximum: 5000
        render:
          type: boolean
        source:
          type: string
          enum:
            - links
            - sitemap
            - all
          default: links
        autoConsent:
          type: boolean
          default: true
        maxDepth:
          type: integer
          minimum: 0
          maximum: 2
        includePaths:
          type: array
          items:
            type: string
        excludePaths:
          type: array
          items:
            type: string
        format:
          type: string
        callback_url:
          type: string
          format: uri
    AgentRequest:
      type: object
      required:
        - instruction
      additionalProperties: false
      properties:
        instruction:
          type: string
          minLength: 1
          maxLength: 2000
        max_steps:
          type: integer
          minimum: 1
          maximum: 100
        budget_usd:
          type: number
          minimum: 0
          maximum: 10
        max_scrapes:
          type: integer
          minimum: 0
          maximum: 5000
        response_format:
          type: string
          enum:
            - text
            - json
        json_schema:
          type: object
          additionalProperties: true
        async:
          type: boolean
        auto_confirm:
          type: boolean
          default: false
        conversation_id:
          type: string
