{
  "openapi": "3.1.0",
  "info": {
    "title": "domscout API",
    "version": "1.1.0",
    "description": "The additive v1 HTTP contract for domscout browser capture, DOM inspection, automation, durable jobs, batches, crawls, and webhooks. Existing screenshot clients remain compatible; all new request fields are optional unless a schema says otherwise. Every API response sends Cache-Control: no-store and X-Content-Type-Options: nosniff; authenticated responses may contain temporary presigned artifact capabilities and must not be stored by intermediaries."
  },
  "servers": [
    {
      "url": "https://api.domscout.io",
      "description": "Current production AWS API Gateway deployment"
    }
  ],
  "tags": [
    {
      "name": "Capture",
      "description": "Screenshot, PDF, DOM-inspection, automation, and extraction requests."
    },
    {
      "name": "Jobs",
      "description": "Durable asynchronous work and cancellation."
    },
    {
      "name": "Batch",
      "description": "A bounded collection of independent capture jobs."
    },
    {
      "name": "Crawl",
      "description": "A bounded, allowlisted, robots-aware site crawl."
    },
    {
      "name": "Discovery",
      "description": "URL discovery from XML sitemaps and same-site page links."
    },
    {
      "name": "AI",
      "description": "Provider-backed structured extraction from supplied page content."
    },
    {
      "name": "Search",
      "description": "External web search with optional guarded result scraping."
    },
    {
      "name": "Semantic Index",
      "description": "Account-scoped embedding, indexing, and semantic retrieval."
    },
    {
      "name": "Webhooks",
      "description": "Stored outbound webhook deliveries and manual replay."
    },
    {
      "name": "Operations",
      "description": "Authenticated internal operational delivery endpoints; not for customer API keys."
    },
    {
      "name": "Account",
      "description": "Credit balance, quota, and pricing. Never billed."
    },
    {
      "name": "Feedback",
      "description": "The calling model reports a problem, gap, or idea. Never billed."
    },
    {
      "name": "Monitors",
      "description": "Scheduled unattended checks of a URL, and their run history."
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "paths": {
    "/screenshot": {
      "post": {
        "tags": [
          "Capture"
        ],
        "operationId": "submitScreenshot",
        "summary": "Capture a page, inspect its DOM, and optionally automate it",
        "description": "Browser execution is CONDITIONAL, not held outright. Production captures run only inside the isolated renderer, which was deployed and verified on 2026-07-30 (api/browser-isolation.js records ISOLATED; api/udp-containment.js records CONTAINED). Two gates decide whether a given request may start a browser, and neither is a plan gate: renderer isolation must be proven, and capturing an ARBITRARY PUBLIC URL additionally requires the deployment switch PUBLIC_CAPTURE_ENABLED=true — accounts holding the internal entitlement are unaffected by the second. A request refused by either gate returns 403 and carries no upgrade_url: code BROWSER_ISOLATION_REQUIRED when isolation is not proven, and code BROWSER_EXECUTION_DENIED with reason public_capture_not_enabled when the public-capture switch is off. Returns a direct result when it fits within the synchronous response budget; explicit async requests and rich results that exceed it return 202 with a durable job ID instead. Set responseType to json whenever semantic analysis, diagnostics, extraction, cleanup reporting, or action results are needed. A binary response is raw image/PDF bytes; the deployment template configures API Gateway binary handling independently of the ordering of values in Accept.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScreenshotRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Synchronous capture result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScreenshotResponse"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-Domscout-Capture-Id": {
                "$ref": "#/components/headers/CaptureId"
              },
              "X-Domscout-Capture-Expires-At": {
                "$ref": "#/components/headers/CaptureExpiresAt"
              }
            }
          },
          "202": {
            "description": "The request was explicitly asynchronous or automatically promoted to a durable job.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "206": {
            "description": "The action budget ended after some action/timeline work completed. metadata.budgetWarning names the budget that applied: 24s synchronous, 52s for async and other worker-executed captures.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScreenshotResponse"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "504": {
            "description": "The browser session timed out during navigation or while executing actions, or did not finish before the synchronous capture deadline (`RENDER_DEADLINE_EXCEEDED`). When frames were captured before an action timeout the body includes partialResult and timelineBase64. Retry with async:true to run outside the synchronous window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/scrape": {
      "post": {
        "summary": "Read a page as Markdown, with or without a browser",
        "operationId": "submitScrape",
        "tags": [
          "Capture"
        ],
        "description": "The same capture engine POST /screenshot runs, addressed as a content endpoint. It defaults extractMarkdown:true and forces responseType:json, and it drops the base64 image from the response unless screenshot:true asks for it — which is what keeps a text answer inside the synchronous response budget on pages whose PNG would not fit.\n\nEvery field, plan gate, entitlement, credit weight and error contract is POST /screenshot's. The only differences are the three defaults above and the response shape.\n\nSend renderJs:false (or fast:true) to answer from one guarded HTTP GET instead of a browser. That path is roughly an order of magnitude faster, costs the same credits, and returns the identical document shape — but it does not execute JavaScript, so check metadata.renderJs and metadata.contentQuality before concluding a page is empty. renderJs:false is also accepted on POST /screenshot, where it returns this document shape because there is no image to return.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScreenshotRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The page as a document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScrapeResponse"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-Domscout-Capture-Id": {
                "$ref": "#/components/headers/CaptureId"
              },
              "X-Domscout-Capture-Expires-At": {
                "$ref": "#/components/headers/CaptureExpiresAt"
              }
            }
          },
          "202": {
            "description": "The request was explicitly asynchronous or automatically promoted to a durable job.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "206": {
            "description": "The action budget ended after some action/timeline work completed. metadata.budgetWarning names the budget that applied: 24s synchronous, 52s for async and other worker-executed captures.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScreenshotResponse"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "415": {
            "description": "renderJs:false was asked to read a non-textual payload (a PDF, an image, a binary download). Retry with renderJs:true, which renders it in the browser.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "504": {
            "description": "The browser session timed out during navigation or while executing actions, or did not finish before the synchronous capture deadline (`RENDER_DEADLINE_EXCEEDED`). When frames were captured before an action timeout the body includes partialResult and timelineBase64. Retry with async:true to run outside the synchronous window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/captures": {
      "get": {
        "tags": [
          "Capture"
        ],
        "operationId": "listSavedCaptures",
        "summary": "List retained saved-capture metadata",
        "description": "Returns non-expired captures owned by the API key's account. The response never includes S3 object keys or signed URLs; retrieve one capture through GET /capture/{captureId} when an artifact is needed. This is a free control-plane read.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CollectionLimit"
          },
          {
            "$ref": "#/components/parameters/CollectionOffset"
          }
        ],
        "responses": {
          "200": {
            "description": "A bounded, newest-first page of retained capture metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedCaptureListResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/jobs": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "operationId": "listJobs",
        "summary": "List durable jobs for this account",
        "description": "Returns safe metadata for durable jobs owned by this account, including child jobs. Inputs, result artifact keys, and raw payloads are never returned. This is a free control-plane read.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CollectionLimit"
          },
          {
            "$ref": "#/components/parameters/CollectionOffset"
          }
        ],
        "responses": {
          "200": {
            "description": "A bounded, newest-first page of durable jobs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobListResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/capture/{captureId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CaptureId"
        }
      ],
      "get": {
        "tags": [
          "Capture"
        ],
        "operationId": "getSavedCapture",
        "summary": "Get a saved capture and short-lived artifact download URLs",
        "description": "Requires an API key owned by the capture's account. The service deliberately returns the same 404 response when the capture is absent, a finite-retention capture has expired, or it belongs to another account. New saves have a finite plan-bounded expiry; a historic saved row with expiresAt null is legacy permanent retention. The response has no separate S3 object-key field, but a signed downloadUrl can contain storage-path information and is a secret capability: do not log it or expose it to an untrusted client. Each URL expires no later than one hour after issuance and, for a finite-retention capture, is clamped not to outlive it.",
        "responses": {
          "200": {
            "description": "Owned retained saved-capture metadata and signed artifact download URLs (finite-retention or legacy permanent).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaptureLookupResponse"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/job/{jobId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/JobId"
        }
      ],
      "get": {
        "tags": [
          "Jobs"
        ],
        "operationId": "getJob",
        "summary": "Get a durable job and its result when complete",
        "responses": {
          "200": {
            "description": "Job state. A completed job can include its safe result; it does not promise saved-capture retention or artifact descriptors.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobStatus"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Jobs"
        ],
        "operationId": "cancelJob",
        "summary": "Request cancellation of a durable job",
        "description": "Cancellation is cooperative. Work already running may finish, while unstarted children are cancelled without consuming page quota.\n\n**Work already in flight is still charged.** A capture is claimed by its worker within about a second of submission, so a cancellation for a single capture almost always arrives after the browser has started and that capture is billed as a completed one; the credit is not refunded. What cancellation saves is the unstarted remainder — for a batch or crawl, every child that had not yet been claimed. Read the response's counts rather than assuming a cancelled job cost nothing, and treat `GET /credits` as authoritative for what was actually spent.",
        "responses": {
          "200": {
            "description": "The job was already terminal or cancellation completed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobStatus"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "202": {
            "description": "Cancellation was requested and will be observed by the worker.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobStatus"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/job/{jobId}/metadata": {
      "parameters": [
        {
          "$ref": "#/components/parameters/JobId"
        }
      ],
      "get": {
        "tags": [
          "Jobs"
        ],
        "operationId": "getJobMetadata",
        "summary": "Get safe job metadata without loading rich result content",
        "responses": {
          "200": {
            "description": "Job timing, state, a safe result summary, and aggregate counts. It does not promise saved-capture retention or artifact descriptors; retrieve an owned saved capture through GET /capture/{captureId} instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobMetadata"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/batch": {
      "post": {
        "tags": [
          "Batch"
        ],
        "operationId": "submitBatch",
        "summary": "Submit up to 100 independent capture requests",
        "description": "Requires the Business plan or higher. A Pro or Hobby key receives 403 with code PLAN_FEATURE_UNAVAILABLE and an upgrade_url. Business and Enterprise keys can submit normally; when the deployment-wide product emergency pause is active, they receive 403 FEATURE_NOT_ENABLED without an upgrade_url and GET /credits reports capabilities.routes[\"/batch\"].reason as platform. This route is not billed, but the gates still apply: \"free\" means no credit is charged, not that every account may call it.\n\nEach item becomes a bounded child job. Results are aggregated through the returned parent job.\n\n**One parent workflow at a time.** A single API key may have only one batch or crawl active (pending, processing, retrying, or cancel_requested). A second submission while one is running is refused with 409 and code WORKFLOW_ALREADY_ACTIVE, and the response's existingJobId names the blocking job. Recover by polling that job until it reaches a terminal state, or by cancelling it with DELETE. The limit is per API key, so separate keys on the same account run independently. Note that a submission which times out at the gateway may still be running: the work continues server-side, so a 504 on submit can be followed by this 409 on the next attempt even though nothing looks active from the caller's side.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent replay of a batch workflow that has already reached a terminal state (done, error, or cancelled). The body carries replayed:true and the final counts. A replay of a workflow that is still running returns 202 instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ParentJobAccepted"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "202": {
            "description": "Batch parent job accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ParentJobAccepted"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/batch/{jobId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/JobId"
        }
      ],
      "get": {
        "tags": [
          "Batch"
        ],
        "operationId": "getBatch",
        "summary": "Get aggregate batch status and completed child results",
        "responses": {
          "200": {
            "description": "Batch parent status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ParentJobStatus"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Batch"
        ],
        "operationId": "cancelBatch",
        "summary": "Cancel a batch and its unstarted child jobs",
        "responses": {
          "200": {
            "description": "Batch is terminal or was cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ParentJobStatus"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "202": {
            "description": "Cancellation was requested.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ParentJobStatus"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/crawl": {
      "post": {
        "tags": [
          "Crawl"
        ],
        "operationId": "submitCrawl",
        "summary": "Submit a bounded allowlisted site crawl",
        "description": "Requires the Business plan or higher. A Pro or Hobby key receives 403 with code PLAN_FEATURE_UNAVAILABLE and an upgrade_url. Business and Enterprise keys can submit normally; when the deployment-wide product emergency pause is active, they receive 403 FEATURE_NOT_ENABLED without an upgrade_url and GET /credits reports capabilities.routes[\"/crawl\"].reason as platform. This route is not billed, but the gates still apply: \"free\" means no credit is charged, not that every account may call it.\n\nCrawls use one queued child job per page. Only HTTPS URLs passing the service SSRF guard and the caller's allowedOrigins policy are eligible. Every started child capture uses the normal capture waterfall: included monthly quota, then prepaid credits, then permitted plan overage. There is no separate crawl-page quota. Once all created child items are terminal, the parent is terminalized promptly rather than waiting for a periodic reconciler.\n\n**One parent workflow at a time.** A single API key may have only one batch or crawl active (pending, processing, retrying, or cancel_requested). A second submission while one is running is refused with 409 and code WORKFLOW_ALREADY_ACTIVE, and the response's existingJobId names the blocking job. Recover by polling that job until it reaches a terminal state, or by cancelling it with DELETE. The limit is per API key, so separate keys on the same account run independently. Note that a submission which times out at the gateway may still be running: the work continues server-side, so a 504 on submit can be followed by this 409 on the next attempt even though nothing looks active from the caller's side.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CrawlRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent replay of a crawl workflow that has already reached a terminal state (done, error, or cancelled). The body carries replayed:true and the final counts. A replay of a workflow that is still running returns 202 instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ParentJobAccepted"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "202": {
            "description": "Crawl parent job accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ParentJobAccepted"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/crawl/{jobId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/JobId"
        }
      ],
      "get": {
        "tags": [
          "Crawl"
        ],
        "operationId": "getCrawl",
        "summary": "Get crawl frontier, aggregate status, and completed page results",
        "responses": {
          "200": {
            "description": "Crawl parent status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ParentJobStatus"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Crawl"
        ],
        "operationId": "cancelCrawl",
        "summary": "Cancel a crawl and stop scheduling unstarted pages",
        "responses": {
          "200": {
            "description": "Crawl is terminal or was cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ParentJobStatus"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "202": {
            "description": "Cancellation was requested.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ParentJobStatus"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/map": {
      "post": {
        "tags": [
          "Discovery"
        ],
        "operationId": "mapSite",
        "summary": "Discover URLs from sitemaps and page links",
        "description": "Returns a bounded, robots-aware URL map. Sitemap locations and same-site links are deduplicated and canonicalized. The endpoint does not execute JavaScript. Intelligence work has one 18-second synchronous deadline across the complete request.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MapRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Discovered URLs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapResponse"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/IntelligenceFinalizationUncertain"
          },
          "504": {
            "$ref": "#/components/responses/IntelligenceDeadlineExceeded"
          }
        }
      }
    },
    "/extract": {
      "post": {
        "tags": [
          "AI"
        ],
        "operationId": "extractStructuredData",
        "summary": "Extract structured JSON with an LLM",
        "description": "Accepts a URL, HTML, or text content plus a prompt and JSON Schema. The configured LLM provider must return JSON that passes the schema validator. When the first valid JSON object fails that schema, the service may make one corrective provider call inside the same request deadline; a second mismatch remains AI_SCHEMA_VALIDATION_FAILED. Requires Pro or higher. Intelligence work has one 18-second synchronous deadline across the complete request.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExtractRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Validated structured extraction.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtractResponse"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/IntelligenceServiceUnavailable"
          },
          "504": {
            "$ref": "#/components/responses/IntelligenceDeadlineExceeded"
          }
        }
      }
    },
    "/search": {
      "post": {
        "tags": [
          "Search"
        ],
        "operationId": "searchWeb",
        "summary": "Search the web and optionally scrape result pages (WITHHELD)",
        "description": "WITHHELD AS OF 2026-08-12. This deployment serves no search provider, so every call answers 503 SEARCH_NOT_CONFIGURED regardless of plan or key. It is documented because the route exists and must be described accurately, not because it is offered. Read `capabilities.routes[\"/search\"]` from GET /credits before calling it: while it reports available:false with reason \"deployment\", nothing you can change as a caller will make this route return results. Marked deprecated so generated clients surface the state rather than presenting it as usable; the marker will be removed when a provider is chosen.\n\nWhen a provider IS configured, the route uses it and then fetches result pages through domscout's guarded transport and robots policy. Requires Pro or higher. Intelligence work has one 18-second synchronous deadline across the complete request.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search results and optional page text.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/IntelligenceServiceUnavailable"
          },
          "504": {
            "$ref": "#/components/responses/IntelligenceDeadlineExceeded"
          }
        },
        "deprecated": true
      }
    },
    "/index": {
      "post": {
        "tags": [
          "Semantic Index"
        ],
        "operationId": "indexContent",
        "summary": "Chunk, embed, and store content in the account vector index",
        "description": "Stores account-scoped content in Supabase pgvector using the configured embedding provider. Requires Pro or higher. Intelligence work has one 18-second synchronous deadline across the complete request.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IndexRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Index document created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IndexResponse"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/IntelligenceServiceUnavailable"
          },
          "504": {
            "$ref": "#/components/responses/IntelligenceDeadlineExceeded"
          }
        }
      }
    },
    "/semantic-search": {
      "post": {
        "tags": [
          "Semantic Index"
        ],
        "operationId": "searchSemanticIndex",
        "summary": "Search indexed content by semantic similarity",
        "description": "Embeds the query and returns the closest account-owned chunks using cosine similarity. Requires Pro or higher. Intelligence work has one 18-second synchronous deadline across the complete request.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SemanticSearchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Matching indexed chunks.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SemanticSearchResponse"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/IntelligenceServiceUnavailable"
          },
          "504": {
            "$ref": "#/components/responses/IntelligenceDeadlineExceeded"
          }
        }
      }
    },
    "/webhooks/deliveries/{deliveryId}/replay": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DeliveryId"
        }
      ],
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "replayWebhookDelivery",
        "summary": "Queue a signed replay of a stored webhook delivery",
        "description": "The original persisted payload and configured signing secret are used. This does not run a browser capture.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Replay delivery accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookReplayAccepted"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/internal/checkout-alarm": {
      "post": {
        "tags": [
          "Operations"
        ],
        "operationId": "receiveCheckoutAlarm",
        "summary": "Publish an authenticated checkout alarm to the stack SNS topic",
        "description": "Server-to-server endpoint used by the checkout reconciler. The bearer token is generated and stored in AWS Secrets Manager; customer API keys are not accepted.",
        "security": [
          {
            "AlarmBearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "maxProperties": 64,
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "SNS accepted the alarm message. No credit, quota or rate-limit headers are returned: this route carries no API key and reserves no usage, so there is no account for them to describe. They were declared here in error and internal health tooling that waited for them would have waited forever."
          },
          "400": {
            "description": "The body is not a JSON object."
          },
          "401": {
            "description": "The bearer token is absent or invalid."
          },
          "413": {
            "description": "The request body exceeds 64 KiB."
          },
          "500": {
            "description": "The receiver could not read its secret or publish to SNS."
          }
        }
      }
    },
    "/credits": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getCredits",
        "summary": "Credit balance, quota, capabilities, and the credit price list",
        "description": "Everything needed to budget a run, without spending anything. This request is NOT billed: it consumes no credits and no quota, and is subject only to the per-second rate limit.\n\nReturns the current credit balance, month-to-date quota usage, the overage ceiling, the per-second rate limit, and the full credit weight table so a client can price a request before sending it.\n\nThe quota resets on the first of each calendar month (UTC). This is true on an annual subscription as well: an annual plan buys the same monthly allowance twelve times over, not twelve months of allowance to spend at once.\n\nIt also reports which gated capabilities this key can actually use, and why not when it cannot. The normal DOM product is plan-based, but provider-backed routes depend on what this deployment has configured, the product group can be paused globally for rollback, and trusted browser-side JavaScript has its own account entitlement. Read `capabilities` before spending a billed request on /extract, /search, /index, /semantic-search, /batch, /crawl, or a gated capture option.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current balance, quota, capability availability, and price list.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditSummary"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "403": {
            "description": "Missing, invalid, or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Quota and credits are never a reason for this endpoint to refuse.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/feedback": {
      "post": {
        "tags": [
          "Feedback"
        ],
        "operationId": "submitFeedback",
        "summary": "Report a problem, a documentation gap, or an idea",
        "description": "A direct channel from the calling model or developer to the domscout team. **This request is never billed** — it consumes no credits and no quota, and is subject only to the per-second rate limit and a daily report cap.\n\nUse it when an error message was not actionable, a documented parameter did not behave as described, a capture succeeded but returned the wrong thing, or a capability you needed was missing. Include `requestId` when the report is about a specific request and the server will attach its own record of that request — status, error, latency, and the parameters it ran with — so there is no need to restate them.\n\nReports are read by humans. Do not send secrets; the server strips credential-shaped strings before storing, but the cheapest redaction is not sending them.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedbackRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Recorded. Not charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedbackAccepted"
                }
              }
            },
            "headers": {
              "X-Domscout-Credits-Cost": {
                "$ref": "#/components/headers/CreditsCost"
              },
              "X-Domscout-Credits-Remaining": {
                "$ref": "#/components/headers/CreditsRemaining"
              },
              "X-Domscout-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              }
            }
          },
          "400": {
            "description": "message is missing or empty. Everything else is coerced rather than rejected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Missing, invalid, or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Per-second rate limit, or the daily report cap for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/monitors": {
      "post": {
        "operationId": "createMonitor",
        "tags": [
          "Monitors"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "Create a monitor",
        "description": "A monitor is a standing instruction to capture a URL unattended on a schedule and report what changed. It carries the same API-key authentication and the same browser-execution gate as a capture, because it is a capture with a timer.\n\nPlan ceilings: Hobby 0 monitors (403 PLAN_FEATURE_UNAVAILABLE), Pro 10 at a minimum interval of 60 minutes, Business 100 at 15 minutes, Enterprise 500 at 5 minutes. GET /credits reports availability under capabilities.routes[\"/monitors\"].\n\nManagement calls are not billed. Each RUN reserves capture quota exactly as a scheduled check does, priced from the monitor's own captureParams.\n\nIf notifyWebhookUrl is set, the creation response carries notifyWebhookSecret. No API read returns it, so store it on receipt. Unlike an API key it is not unrecoverable: the account owner can reveal it in the dashboard, and POST /monitors/{monitorId}/rotate-secret replaces it, disclosing the replacement in that response.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "targetUrl"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 160
                  },
                  "targetUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "intervalMinutes": {
                    "type": "integer",
                    "default": 1440,
                    "description": "At least the plan minimum, at most 43200 (30 days)."
                  },
                  "captureParams": {
                    "type": "object"
                  },
                  "notifyWebhookUrl": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uri",
                    "description": "HTTPS only. Change notifications are signed with the secret returned at creation."
                  },
                  "checkMarkdown": {
                    "type": "boolean",
                    "default": true
                  },
                  "checkLinks": {
                    "type": "boolean",
                    "default": true
                  },
                  "checkTitle": {
                    "type": "boolean",
                    "default": true
                  },
                  "checkStatusCode": {
                    "type": "boolean",
                    "default": true
                  },
                  "checkDom": {
                    "type": "boolean",
                    "default": false
                  },
                  "domIgnoreSelectors": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  },
                  "domIgnoreAttributes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  },
                  "domIgnoreTextPatterns": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  },
                  "domPositionTolerancePx": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000,
                    "default": 2
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "monitor": {
                      "$ref": "#/components/schemas/Monitor"
                    },
                    "notifyWebhookSecret": {
                      "type": "string",
                      "description": "Present only when notifyWebhookUrl was set. No API read returns it; the account owner can reveal it in the dashboard."
                    },
                    "notifyWebhookSecretNote": {
                      "type": "string",
                      "description": "Present with notifyWebhookSecret and explains its one-time disclosure."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Plan ceiling, or a platform hold.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate or quota wall.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "get": {
        "operationId": "listMonitors",
        "tags": [
          "Monitors"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "List this account's monitors",
        "description": "Newest first. Never includes a signing secret.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Monitors.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "monitors": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Monitor"
                      }
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    },
                    "plan": {
                      "type": "object",
                      "properties": {
                        "maxMonitors": {
                          "type": "integer"
                        },
                        "minIntervalMinutes": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/monitors/{monitorId}": {
      "get": {
        "operationId": "getMonitor",
        "tags": [
          "Monitors"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "monitorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "summary": "Read one monitor",
        "description": "A monitor belonging to another account answers 404 MONITOR_NOT_FOUND, identically to one that does not exist: any distinction would be an id oracle.",
        "responses": {
          "200": {
            "description": "The monitor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "monitor": {
                      "$ref": "#/components/schemas/Monitor"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateMonitor",
        "tags": [
          "Monitors"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "monitorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "summary": "Update, pause, or resume a monitor",
        "description": "Only the fields you send are changed. Send status to pause or resume: \"paused\" always succeeds, \"active\" is re-checked against the plan ceiling and the browser-execution gate, because resuming is the transition that can put an account over its limit. The quota check, the status change and the field updates happen in one transaction, so a patch either fully applies or not at all.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 160
                  },
                  "targetUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "paused"
                    ]
                  },
                  "intervalMinutes": {
                    "type": "integer",
                    "description": "At least the plan minimum, at most 43200 (30 days)."
                  },
                  "captureParams": {
                    "type": "object"
                  },
                  "notifyWebhookUrl": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uri",
                    "description": "HTTPS only."
                  },
                  "checkMarkdown": {
                    "type": "boolean"
                  },
                  "checkLinks": {
                    "type": "boolean"
                  },
                  "checkTitle": {
                    "type": "boolean"
                  },
                  "checkStatusCode": {
                    "type": "boolean"
                  },
                  "checkDom": {
                    "type": "boolean"
                  },
                  "domIgnoreSelectors": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "domIgnoreAttributes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "domIgnoreTextPatterns": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "domPositionTolerancePx": {
                    "type": "number"
                  }
                },
                "additionalProperties": false,
                "description": "Any creation field, plus status."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "monitor": {
                      "$ref": "#/components/schemas/Monitor"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Plan ceiling on resume.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteMonitor",
        "tags": [
          "Monitors"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "monitorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "summary": "Delete a monitor",
        "description": "Permanent. Run history is removed with it.",
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "monitorId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/monitors/{monitorId}/rotate-secret": {
      "post": {
        "operationId": "rotateMonitorWebhookSecret",
        "tags": [
          "Monitors"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "monitorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "summary": "Rotate a monitor webhook signing secret",
        "description": "Replaces the signing secret for an owned monitor that has notifyWebhookUrl configured. The response is the only disclosure of the replacement: monitor reads and lists never include it. Store it on receipt.\n\nEvery accepted call creates a new secret; this operation is not idempotent. Deliveries already queued retain the secret snapshotted when they were accepted, so a receiver should accept both the previous and replacement secrets until those attempts drain.\n\nA missing, foreign, or notification-less monitor answers the same 404 MONITOR_NOT_FOUND. Never billed and never launches a browser.",
        "responses": {
          "200": {
            "description": "Rotated. The replacement secret is shown only in this response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "monitorId",
                    "notifyWebhookSecret",
                    "notifyWebhookSecretNote"
                  ],
                  "properties": {
                    "monitorId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "notifyWebhookSecret": {
                      "type": "string",
                      "minLength": 1,
                      "description": "The replacement signing secret. No API read returns it; the account owner can reveal it in the dashboard."
                    },
                    "notifyWebhookSecretNote": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "The monitor is missing, foreign, or has no notification URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/monitors/{monitorId}/run": {
      "post": {
        "operationId": "runMonitorNow",
        "tags": [
          "Monitors"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "monitorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "summary": "Run a monitor now, once",
        "description": "Enqueues exactly one extra check immediately, without waiting for the interval and without advancing the schedule — the next scheduled run still happens when it was going to.\n\nBounded three ways: one run per call, with no count parameter; refused with 409 MONITOR_RUN_IN_FLIGHT while a run for this monitor is already pending or running, so it cannot be used to fan out; and billed exactly like a scheduled run, drawing on the same quota and refused by the same 429 wall.\n\nA paused monitor is refused with 409 MONITOR_PAUSED. Poll GET /monitors/{monitorId}/runs for the outcome.",
        "responses": {
          "202": {
            "description": "Queued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "monitorId": {
                      "type": "string"
                    },
                    "monitorRunId": {
                      "type": "string"
                    },
                    "pollUrl": {
                      "type": "string"
                    },
                    "creditCost": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "A platform hold on browser execution.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Paused, or a run is already in flight.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate or quota wall.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/monitors/{monitorId}/runs": {
      "get": {
        "operationId": "listMonitorRuns",
        "tags": [
          "Monitors"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "monitorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          }
        ],
        "summary": "Read a monitor's run history",
        "description": "Newest first. changeDetected and changedFields are what a check concluded; captureId points at the saved artifact for that run.",
        "responses": {
          "200": {
            "description": "Runs.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "monitorId": {
                      "type": "string"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "runs": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/MonitorRun"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/webhooks/deliveries": {
      "get": {
        "operationId": "listWebhookDeliveries",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "List this account's webhook deliveries",
        "description": "Newest first, and never billed. This is how you obtain a deliveryId — it is generated server-side and appears in no capture response, so without this route the replay endpoint below cannot be called.\n\nThe delivered payload, your endpoint's response body, and the per-delivery signing secret are never returned.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deliveries.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deliveries": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/webhooks/deliveries/{deliveryId}": {
      "get": {
        "operationId": "getWebhookDelivery",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "Read one delivery and its attempt history",
        "description": "Every attempt, in order, with the status your endpoint returned and the latency. A delivery belonging to another account answers 404 DELIVERY_NOT_FOUND, identically to one that does not exist.",
        "parameters": [
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "delivery": {
                      "$ref": "#/components/schemas/WebhookDelivery"
                    },
                    "attempts": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDeliveryAttempt"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "A valid domscout API key."
      },
      "AlarmBearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Generated checkout-alarm receiver token stored in AWS Secrets Manager and the dashboard's server-only deployment environment."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Optional caller-generated key for POST submission. Reusing a key with an identical body for the same owner returns the original job; reusing it with a different body returns 409.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        }
      },
      "JobId": {
        "name": "jobId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "CaptureId": {
        "name": "captureId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "CollectionLimit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Rows per page. Clamped to 1-100; defaults to 50.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 50
        }
      },
      "CollectionOffset": {
        "name": "offset",
        "in": "query",
        "required": false,
        "description": "Number of rows to skip. Clamped to 0-10000; defaults to 0.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10000,
          "default": 0
        }
      },
      "DeliveryId": {
        "name": "deliveryId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The request failed validation.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The request was refused. Returned when the x-api-key header is missing, revoked, or invalid, and when a valid key is blocked by a plan entitlement, the trusted-JavaScript account entitlement, a global product pause, or a security policy. A plan-only restriction returns code PLAN_FEATURE_UNAVAILABLE and can include upgrade_url. FEATURE_NOT_ENABLED identifies either the global product emergency pause or an eligible Business account without trusted-JavaScript permission; it carries no upgrade_url, so upgrading or retrying cannot clear it. Browser capture carries two platform gates that are NOT plan gates and therefore carry no upgrade_url: code BROWSER_ISOLATION_REQUIRED, returned while renderer isolation is not proven, and code BROWSER_EXECUTION_DENIED with reason public_capture_not_enabled, returned when an account without the internal-capture override captures an arbitrary public URL while PUBLIC_CAPTURE_ENABLED is off. Renderer isolation is not resolved by changing plan or key. The API does not use 401: it authenticates with an API key header rather than an HTTP authentication scheme, so there is no WWW-Authenticate challenge to issue.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "The resource does not exist, has expired, or is not owned by this API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "IdempotencyConflict": {
        "description": "The Idempotency-Key was already used with a different request body.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/IdempotencyConflict"
            }
          }
        }
      },
      "TooLarge": {
        "description": "The requested binary response cannot be served synchronously.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RateLimited": {
        "description": "The plan quota or rate limit has been reached.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        },
        "headers": {
          "X-Domscout-Credits-Cost": {
            "$ref": "#/components/headers/CreditsCost"
          },
          "X-Domscout-Credits-Remaining": {
            "$ref": "#/components/headers/CreditsRemaining"
          },
          "X-Domscout-Quota-Remaining": {
            "$ref": "#/components/headers/QuotaRemaining"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "Retry-After": {
            "description": "Seconds to wait before retrying. Always 1 while every plan's window is per-second.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        }
      },
      "ServerError": {
        "description": "An unexpected service error occurred.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "IntelligenceDeadlineExceeded": {
        "description": "The shared 18-second synchronous intelligence-work deadline expired. In that case the response code is `INTELLIGENCE_DEADLINE_EXCEEDED`. For a URL-based /extract request, retry with a bounded content or HTML excerpt from the page rather than asking the service to fetch it again; that advice is what the response carries, and when fetching the page alone exhausted the budget the message says so, because no model call was attempted. Other intelligence routes should retry with a smaller input or fewer pages. A provider that reaches its own shorter timeout first retains its provider-specific timeout code.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "IntelligenceFinalizationUncertain": {
        "description": "The request work may have completed, but the service could not confirm its usage-finalization write. The response code is `INTELLIGENCE_FINALIZATION_UNCERTAIN`; no result is returned. Its state can be ambiguous (including a possible completed index write), so do not automatically retry. Retain `requestId` and contact support so the outcome can be investigated; any pending usage record is reconciled separately.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "IntelligenceServiceUnavailable": {
        "description": "A required intelligence provider is unavailable or misconfigured. This response can also have code `INTELLIGENCE_FINALIZATION_UNCERTAIN`: in that case no result is returned, but the work may have completed, so do not automatically retry. Retain `requestId` and contact support so the outcome can be investigated; any pending usage record is reconciled separately.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "A dependency this request needs is unavailable or not configured for this deployment. Codes: SUPABASE_TIMEOUT and SUPABASE_INVALID_RESPONSE (a storage operation did not answer, or answered unreadably — the write may have committed, so any retry must be idempotent), CAPTURE_ARTIFACT_UNAVAILABLE and CAPTURE_ARTIFACT_CORRUPT (a stored artifact could not be read or parsed), ASYNC_JOBS_NOT_CONFIGURED and CAPTURE_RETRIEVAL_NOT_CONFIGURED (the capability is not configured here, on any plan). Retryable unless the code names a deployment configuration.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "ScreenshotRequest": {
        "type": "object",
        "description": "Existing screenshot options are retained. New inspection, rendering, cleanup, diagnostics, extraction, retention, and action fields are additive.",
        "anyOf": [
          {
            "required": [
              "selector"
            ]
          },
          {
            "required": [
              "url"
            ]
          },
          {
            "required": [
              "html"
            ]
          }
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 4096,
            "description": "Public HTTP(S) page URL. Unsafe addresses and redirects are rejected. Credentials in the authority (https://user:pass@host/) are refused with 400 — send authentication in the headers field instead, so it is never written to a capture log."
          },
          "html": {
            "type": "string",
            "maxLength": 1000000,
            "description": "Raw HTML to render instead of navigating to a URL."
          },
          "format": {
            "type": "string",
            "enum": [
              "png",
              "jpeg",
              "webp",
              "pdf"
            ],
            "default": "png"
          },
          "responseType": {
            "type": "string",
            "enum": [
              "json",
              "binary"
            ],
            "default": "json",
            "description": "How the capture comes back. \"json\" (default) returns a JSON envelope with base64 image data plus metadata and any analysis you requested. \"binary\" returns the raw file bytes with a matching Content-Type, and therefore has nowhere to carry metadata — so a binary request combined with an analysis option (cleanup, semanticSnapshot, diagnostics, or extract) is AUTO-PROMOTED to a durable job: it answers 202 with a jobId and metadata.autoPromotedAsync, and you poll GET /job/{jobId} for the result. A capture that fails after promotion reports its failure on the job rather than as a synchronous 4xx, carrying the same error code it would have returned inline. Binary responses also cannot carry metadata.ignoredFields."
          },
          "async": {
            "type": "boolean",
            "default": false,
            "description": "Force durable asynchronous execution. The service also auto-promotes captures expected to be large (rich JSON output) or slow (a URL capture stacking two or more whole-DOM passes, or one combined with fullPage/lazyScroll). Slow-capture promotion applies to Pro and above; Hobby keeps inline results."
          },
          "probe": {
            "type": "boolean",
            "default": false,
            "description": "Load and measure the page without a screenshot."
          },
          "width": {
            "type": "integer",
            "minimum": 100,
            "maximum": 3840,
            "default": 1280
          },
          "height": {
            "type": "integer",
            "minimum": 100,
            "maximum": 2160,
            "default": 800
          },
          "isMobile": {
            "type": "boolean",
            "default": false
          },
          "hasTouch": {
            "type": "boolean",
            "default": false
          },
          "deviceScaleFactor": {
            "type": "number",
            "minimum": 1,
            "maximum": 3,
            "default": 2
          },
          "quality": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 80
          },
          "fullPage": {
            "type": "boolean",
            "default": false,
            "description": "Capture the whole scrollable page rather than the viewport. Adds a credit surcharge. The rendered page may be at most 12000px tall; beyond that the request is refused with 400 and code CAPTURE_TOO_TALL rather than a truncated image. The same ceiling applies to captureSelector."
          },
          "selector": {
            "type": "string",
            "maxLength": 2000,
            "deprecated": true,
            "description": "Legacy alias for captureSelector."
          },
          "captureSelector": {
            "type": "string",
            "maxLength": 2000,
            "description": "The matched element must be visible within 5000ms, or the request is refused with 400 and code CAPTURE_SELECTOR_NOT_FOUND. It is also subject to the same 12000px ceiling as fullPage (400, CAPTURE_TOO_TALL)."
          },
          "hideSelectors": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string",
              "maxLength": 2000
            }
          },
          "captureMode": {
            "type": "string",
            "enum": [
              "default",
              "grid",
              "skeleton"
            ],
            "default": "default",
            "description": "default uses the requested viewport. grid produces responsive desktop, tablet, and mobile frames without reloading raw inline HTML. skeleton preserves a DOMContentLoaded frame before waiting for bounded hydration, so an inline HTML skeleton is still useful even if later network-idle settling times out. grid and skeleton also honour extractMarkdown; the Markdown is taken from the DOM after the mode has finished capturing, so for grid that is the final (desktop) viewport."
          },
          "waitForSelector": {
            "type": "string",
            "maxLength": 2000,
            "description": "A wait that expires is a client-side outcome, not a server fault: the request is refused with 400 and code WAIT_FOR_SELECTOR_TIMEOUT."
          },
          "delay": {
            "type": "integer",
            "minimum": 0,
            "maximum": 5000,
            "default": 0
          },
          "headers": {
            "type": "object",
            "maxProperties": 50,
            "additionalProperties": {
              "type": "string",
              "maxLength": 4096
            },
            "description": "Scoped only to requests to the target origin. Do not expect sensitive header values to appear in diagnostics or persisted artifacts."
          },
          "cookies": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "$ref": "#/components/schemas/Cookie"
            }
          },
          "injectCSS": {
            "type": "string",
            "maxLength": 100000
          },
          "injectJS": {
            "type": "string",
            "maxLength": 50000,
            "description": "Trusted-JavaScript feature. It requires an eligible plan, an operator-controlled account entitlement, and the platform-wide emergency switch."
          },
          "aiMode": {
            "type": "boolean",
            "default": false
          },
          "debugOverlay": {
            "type": "boolean",
            "default": false,
            "description": "Render console errors, page exceptions, failed requests and oversized assets into an overlay on the captured image. At most 200 entries are collected and each is truncated to 2048 characters; past that the overlay ends with a [TRUNCATED] marker. For structured, machine-readable output use `diagnostics` instead."
          },
          "performanceOverlay": {
            "type": "boolean",
            "default": false
          },
          "forceState": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ForceState"
            }
          },
          "actions": {
            "type": "array",
            "maxItems": 25,
            "items": {
              "$ref": "#/components/schemas/Action"
            }
          },
          "typeSpeed": {
            "type": "integer",
            "minimum": 0,
            "maximum": 40,
            "default": 40
          },
          "fastType": {
            "type": "boolean",
            "default": false
          },
          "captureTimeline": {
            "type": "boolean",
            "default": false
          },
          "extractMarkdown": {
            "type": "boolean",
            "default": false,
            "description": "Extract agent-readable Markdown. Empty main content falls back to the document body and then the accessibility tree when available."
          },
          "semanticNodes": {
            "type": "boolean",
            "default": false,
            "description": "Legacy interactive-node summary. Prefer semanticSnapshot for rich DOM data."
          },
          "simplifyDom": {
            "type": "boolean",
            "default": false
          },
          "lazyScroll": {
            "type": "boolean",
            "default": false
          },
          "pdfFormat": {
            "type": "string",
            "maxLength": 32,
            "default": "A4",
            "description": "Paper size for a PDF capture. Matched case-insensitively against LETTER, LEGAL, TABLOID, LEDGER, A0, A1, A2, A3, A4, A5 and A6; anything else is refused with 400 and code PDF_FORMAT_UNSUPPORTED, which names the accepted values. An empty or omitted value takes the A4 default."
          },
          "landscape": {
            "type": "boolean",
            "default": false
          },
          "printBackground": {
            "type": "boolean",
            "default": true
          },
          "save": {
            "type": "boolean",
            "default": false,
            "description": "Persist capture artifacts using the configured finite, plan-bounded retention policy. JSON responses include metadata.captureId, metadata.retentionDays, and metadata.captureExpiresAt. A synchronous binary response exposes X-Domscout-Capture-Id and X-Domscout-Capture-Expires-At. Retrieve owned retained artifacts with GET /capture/{captureId}; that route has no separate S3-key field, but its signed downloadUrl can contain storage-path information and is a secret capability URL. Historic rows with expiresAt null are legacy permanent retention."
          },
          "captureName": {
            "type": "string",
            "maxLength": 255
          },
          "retentionDays": {
            "$ref": "#/components/schemas/RetentionDays"
          },
          "callbackUrl": {
            "type": "string",
            "format": "uri",
            "pattern": "^https://",
            "maxLength": 4096,
            "description": "Legacy per-job callback endpoint. Must be public HTTPS without URL credentials and must pass DNS/IP safety checks before acceptance and at every redirect hop."
          },
          "callbackSecret": {
            "type": "string",
            "maxLength": 256,
            "writeOnly": true,
            "description": "Legacy per-job signing secret. It is never returned."
          },
          "semanticSnapshot": {
            "$ref": "#/components/schemas/SemanticSnapshotOptions"
          },
          "diagnostics": {
            "$ref": "#/components/schemas/DiagnosticsOptions"
          },
          "render": {
            "$ref": "#/components/schemas/RenderOptions"
          },
          "cleanup": {
            "$ref": "#/components/schemas/CleanupOptions"
          },
          "extract": {
            "$ref": "#/components/schemas/ExtractOptions"
          },
          "renderJs": {
            "type": "boolean",
            "default": true,
            "description": "Set false to answer from one guarded HTTP GET instead of a browser. Roughly an order of magnitude faster and priced identically, but a page that renders its content with JavaScript returns whatever its server-side HTML says, which is frequently an empty shell. The response always reports metadata.renderJs and metadata.contentQuality so a caller can detect that case and retry with the browser. Refused with 400 VALIDATION_FAILED, naming each field and refunding the reservation, when combined with html, screenshot:true, a field that needs a live page (actions, injectJS, injectCSS, waitForSelector, selector, captureSelector, hideSelectors, forceState, cookies, headers, a non-zero delay, semanticNodes), save:true, or any option that carries a credit surcharge."
          },
          "fast": {
            "type": "boolean",
            "default": false,
            "description": "Alias for renderJs:false. Identical behaviour; both spellings are accepted."
          },
          "screenshot": {
            "type": "boolean",
            "default": false,
            "description": "POST /scrape only. Put the base64 image back in the response, which /scrape drops by default. Ignored by POST /screenshot, which always returns one. Requires a browser, so it cannot be combined with renderJs:false."
          }
        }
      },
      "Cookie": {
        "type": "object",
        "required": [
          "name",
          "value"
        ],
        "properties": {
          "selector": {
            "type": "string",
            "maxLength": 2000
          },
          "name": {
            "type": "string",
            "maxLength": 256
          },
          "value": {
            "type": "string",
            "maxLength": 4096,
            "writeOnly": true
          },
          "domain": {
            "type": "string",
            "maxLength": 255
          },
          "path": {
            "type": "string",
            "maxLength": 1024
          },
          "httpOnly": {
            "type": "boolean"
          },
          "secure": {
            "type": "boolean"
          },
          "sameSite": {
            "type": "string",
            "enum": [
              "Strict",
              "Lax",
              "None"
            ]
          }
        }
      },
      "ForceState": {
        "type": "object",
        "required": [
          "selector",
          "state"
        ],
        "description": "Hold an element in a hover or focus state for the capture, so a screenshot can show a styling that only exists while the user is interacting. The outcome of every entry is reported back in metadata.forceState.",
        "properties": {
          "selector": {
            "type": "string",
            "maxLength": 2000,
            "description": "A CSS selector. If it matches several elements the state is applied to the first, and the result says so."
          },
          "state": {
            "type": "string",
            "enum": [
              "hover",
              "focus"
            ]
          }
        }
      },
      "RetentionDays": {
        "oneOf": [
          {
            "type": "integer",
            "enum": [
              7,
              30,
              90,
              365
            ]
          },
          {
            "type": "string",
            "enum": [
              "permanent"
            ]
          }
        ],
        "description": "Plan-gated artifact retention selection. 365 is Enterprise-only. permanent is deprecated: it is still accepted but now resolves to the plan maximum rather than unlimited retention."
      },
      "SemanticSnapshotOptions": {
        "oneOf": [
          {
            "type": "boolean",
            "description": "true enables the default rich snapshot."
          },
          {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean",
                "default": true
              },
              "maxNodes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10000,
                "default": 10000
              },
              "detail": {
                "type": "string",
                "enum": [
                  "summary",
                  "full"
                ],
                "default": "summary"
              },
              "selectorBundles": {
                "type": "boolean",
                "default": true
              },
              "timing": {
                "type": "string",
                "enum": [
                  "beforeActions",
                  "afterActions",
                  "both"
                ],
                "default": "afterActions"
              },
              "includeIframes": {
                "type": "boolean",
                "default": true
              }
            }
          }
        ]
      },
      "DiagnosticsOptions": {
        "oneOf": [
          {
            "type": "boolean",
            "description": "true enables all bounded, redacted diagnostics."
          },
          {
            "type": "object",
            "properties": {
              "console": {
                "type": "boolean",
                "default": true
              },
              "pageErrors": {
                "type": "boolean",
                "default": true
              },
              "network": {
                "type": "boolean",
                "default": true
              },
              "resources": {
                "type": "boolean",
                "default": true
              },
              "timing": {
                "type": "boolean",
                "default": true
              },
              "maxEntries": {
                "type": "integer",
                "minimum": 1,
                "maximum": 1000,
                "default": 250
              }
            }
          }
        ]
      },
      "RenderOptions": {
        "type": "object",
        "properties": {
          "disableAnimations": {
            "type": "boolean",
            "default": false
          },
          "colorScheme": {
            "type": "string",
            "enum": [
              "light",
              "dark",
              "no-preference"
            ]
          },
          "locale": {
            "type": "string",
            "description": "BCP 47 locale such as en-US."
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone such as Asia/Kolkata."
          },
          "geolocation": {
            "$ref": "#/components/schemas/Geolocation"
          },
          "userAgent": {
            "type": "string",
            "maxLength": 1024,
            "description": "Overrides the browser User-Agent string. The API enforces 1024 characters; a longer value is rejected with 400."
          },
          "transparentBackground": {
            "type": "boolean",
            "default": false
          },
          "blockResourceTypes": {
            "type": "array",
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "document",
                "stylesheet",
                "image",
                "media",
                "font",
                "script",
                "xhr",
                "fetch",
                "websocket",
                "other"
              ]
            }
          },
          "blockDomains": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "type": "string",
              "maxLength": 255,
              "description": "Domain or subdomain suffix to block."
            }
          },
          "capturePadding": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000,
            "default": 0
          },
          "devicePreset": {
            "type": "string",
            "enum": [
              "desktop",
              "iphone13",
              "pixel7",
              "ipad"
            ],
            "description": "Named viewport and device-emulation preset."
          },
          "reducedMotion": {
            "type": "boolean",
            "default": false
          },
          "media": {
            "type": "string",
            "enum": [
              "screen",
              "print"
            ],
            "default": "screen"
          }
        }
      },
      "Geolocation": {
        "type": "object",
        "required": [
          "latitude",
          "longitude"
        ],
        "properties": {
          "latitude": {
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "longitude": {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          "accuracy": {
            "type": "number",
            "minimum": 0
          }
        }
      },
      "CleanupOptions": {
        "oneOf": [
          {
            "type": "boolean",
            "description": "true enables all built-in heuristic cleanup categories."
          },
          {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean",
                "default": true
              },
              "preserveSelectors": {
                "type": "array",
                "maxItems": 100,
                "items": {
                  "type": "string",
                  "maxLength": 2000
                },
                "description": "Elements matching these selectors are never hidden by heuristic cleanup."
              }
            }
          }
        ]
      },
      "ExtractOptions": {
        "type": "object",
        "required": [
          "fields"
        ],
        "properties": {
          "fields": {
            "type": "object",
            "minProperties": 1,
            "maxProperties": 100,
            "additionalProperties": {
              "$ref": "#/components/schemas/ExtractField"
            }
          },
          "strict": {
            "type": "boolean",
            "default": false,
            "description": "Fail the request when a required field is missing."
          }
        }
      },
      "ExtractField": {
        "type": "object",
        "required": [
          "selector",
          "type"
        ],
        "properties": {
          "selector": {
            "type": "string",
            "maxLength": 2000
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "number",
              "boolean",
              "attribute",
              "html",
              "url",
              "list"
            ]
          },
          "attribute": {
            "type": "string",
            "maxLength": 256,
            "description": "Required when type is attribute."
          },
          "all": {
            "type": "boolean",
            "default": false,
            "description": "Return every matching value. list fields always return all matches."
          },
          "required": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "Locator": {
        "description": "A selector-based action target. Semantic snapshot node IDs are inspection evidence only and are intentionally not accepted as durable action targets.",
        "oneOf": [
          {
            "type": "object",
            "required": [
              "css"
            ],
            "properties": {
              "css": {
                "type": "string",
                "maxLength": 2000
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "xpath"
            ],
            "properties": {
              "xpath": {
                "type": "string",
                "maxLength": 4000
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "text"
            ],
            "properties": {
              "text": {
                "$ref": "#/components/schemas/TextLocatorValue"
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "role"
            ],
            "properties": {
              "role": {
                "$ref": "#/components/schemas/RoleLocatorValue"
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "label"
            ],
            "properties": {
              "label": {
                "type": "string",
                "maxLength": 2000
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "placeholder"
            ],
            "properties": {
              "placeholder": {
                "type": "string",
                "maxLength": 2000
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "maxLength": 1024
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "name"
            ],
            "properties": {
              "name": {
                "type": "string",
                "maxLength": 1024
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "testId"
            ],
            "properties": {
              "testId": {
                "type": "string",
                "maxLength": 1024
              },
              "testIdAttribute": {
                "type": "string",
                "maxLength": 256,
                "default": "data-testid"
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "coordinates"
            ],
            "properties": {
              "coordinates": {
                "$ref": "#/components/schemas/Coordinates"
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "TextLocatorValue": {
        "oneOf": [
          {
            "type": "string",
            "maxLength": 2000
          },
          {
            "type": "object",
            "required": [
              "value"
            ],
            "properties": {
              "value": {
                "type": "string",
                "maxLength": 2000
              },
              "exact": {
                "type": "boolean",
                "default": true
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "RoleLocatorValue": {
        "oneOf": [
          {
            "type": "string",
            "maxLength": 128
          },
          {
            "type": "object",
            "required": [
              "role"
            ],
            "properties": {
              "role": {
                "type": "string",
                "maxLength": 128
              },
              "name": {
                "type": "string",
                "maxLength": 2000
              },
              "exact": {
                "type": "boolean",
                "default": true
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "Coordinates": {
        "type": "object",
        "required": [
          "x",
          "y"
        ],
        "properties": {
          "x": {
            "type": "number"
          },
          "y": {
            "type": "number"
          },
          "space": {
            "type": "string",
            "enum": [
              "viewport",
              "document",
              "screenshot"
            ],
            "default": "viewport"
          }
        }
      },
      "FrameTarget": {
        "description": "A same-origin iframe target. Cross-origin frames are reported as metadata only.",
        "type": "object",
        "anyOf": [
          {
            "required": [
              "name"
            ]
          },
          {
            "required": [
              "urlIncludes"
            ]
          }
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 512
          },
          "urlIncludes": {
            "type": "string",
            "maxLength": 4096
          }
        },
        "additionalProperties": false
      },
      "Action": {
        "type": "object",
        "required": [
          "action"
        ],
        "description": "Use target for new locator types. selector remains supported for legacy CSS actions. Required fields depend on action: target for element actions; url for navigate/openTab; text for type/waitForText; key for pressKey; value for select; files for upload; expected for assert.",
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "click",
              "type",
              "scroll",
              "wait",
              "navigate",
              "back",
              "forward",
              "reload",
              "select",
              "check",
              "uncheck",
              "hover",
              "focus",
              "pressKey",
              "scrollIntoView",
              "waitForText",
              "waitForUrl",
              "waitForFunction",
              "waitForRequest",
              "waitForResponse",
              "waitForNetworkIdle",
              "openTab",
              "switchTab",
              "closeTab",
              "assert",
              "upload"
            ]
          },
          "target": {
            "$ref": "#/components/schemas/Locator"
          },
          "selector": {
            "type": "string",
            "maxLength": 2000,
            "deprecated": true,
            "description": "Legacy CSS target. Do not combine with target."
          },
          "frame": {
            "$ref": "#/components/schemas/FrameTarget"
          },
          "tabId": {
            "type": "string",
            "maxLength": 128,
            "description": "openTab: the id for the new tab, refused with 400 VALIDATION_FAILED if a tab with that id is open; omitted, a free tab-N id is generated. switchTab and closeTab: the tab to act on. closeTab refuses to close the last open tab, whatever its id (400 TAB_CLOSE_FORBIDDEN)."
          },
          "url": {
            "type": "string",
            "maxLength": 4096
          },
          "text": {
            "type": "string",
            "maxLength": 2000
          },
          "exact": {
            "type": "boolean",
            "default": true
          },
          "key": {
            "type": "string",
            "maxLength": 128,
            "description": "Puppeteer key name, for example Enter, Tab, or Control+A."
          },
          "amount": {
            "type": "number",
            "minimum": -5000,
            "maximum": 5000,
            "default": 500
          },
          "time": {
            "type": "integer",
            "minimum": 0,
            "maximum": 5000,
            "default": 1000
          },
          "value": {
            "oneOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "array",
                "maxItems": 50,
                "items": {
                  "type": "string",
                  "maxLength": 2000
                }
              }
            ]
          },
          "expression": {
            "type": "string",
            "maxLength": 4096,
            "description": "Trusted-JavaScript only; waitForFunction requires the same plan, account entitlement, and platform-wide emergency switch as injectJS."
          },
          "files": {
            "type": "array",
            "minItems": 1,
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/UploadFile"
            }
          },
          "expected": {
            "type": "string",
            "maxLength": 2048,
            "description": "Assertion expression: exists, visible, checked, unchecked, disabled, enabled, text:VALUE, or equals:VALUE."
          },
          "continueOnError": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "UploadFile": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "base64",
              "name"
            ],
            "properties": {
              "base64": {
                "type": "string",
                "contentEncoding": "base64",
                "writeOnly": true
              },
              "name": {
                "type": "string",
                "maxLength": 255
              },
              "mimeType": {
                "type": "string",
                "maxLength": 255
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "s3Key",
              "name"
            ],
            "properties": {
              "s3Key": {
                "type": "string",
                "maxLength": 2048,
                "deprecated": true,
                "description": "Withdrawn on 2026-07-30 and always rejected with 400. Browser uploads execute in the isolated renderer, which has no capture-bucket permission and no account identity to check ownership against. Send the file inline as base64 instead."
              },
              "name": {
                "type": "string",
                "maxLength": 255
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "Assertion": {
        "type": "object",
        "required": [
          "kind"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "visible",
              "hidden",
              "text",
              "url",
              "checked",
              "unchecked",
              "value",
              "count"
            ]
          },
          "expected": {
            "type": [
              "string",
              "number",
              "boolean"
            ]
          },
          "exact": {
            "type": "boolean",
            "default": true
          }
        }
      },
      "ScreenshotResponse": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "metadata": {
            "$ref": "#/components/schemas/ScreenshotMetadata"
          },
          "screenshotBase64": {
            "type": "string",
            "contentEncoding": "base64"
          },
          "pdfBase64": {
            "type": "string",
            "contentEncoding": "base64"
          },
          "mobileBase64": {
            "type": "string",
            "contentEncoding": "base64"
          },
          "tabletBase64": {
            "type": "string",
            "contentEncoding": "base64"
          },
          "desktopBase64": {
            "type": "string",
            "contentEncoding": "base64"
          },
          "skeletonBase64": {
            "type": "string",
            "contentEncoding": "base64"
          },
          "hydratedBase64": {
            "type": "string",
            "contentEncoding": "base64"
          },
          "timelineBase64": {
            "type": "array",
            "items": {
              "type": "string",
              "contentEncoding": "base64"
            }
          },
          "markdown": {
            "type": "string"
          },
          "markdownMeta": {
            "$ref": "#/components/schemas/MarkdownMetadata"
          },
          "links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExtractedLink"
            }
          },
          "interactiveNodes": {
            "type": "array",
            "description": "Legacy interactive-node summary.",
            "items": {
              "$ref": "#/components/schemas/InteractiveNode"
            }
          },
          "simplifiedDom": {
            "type": "string"
          },
          "performanceMetrics": {
            "$ref": "#/components/schemas/PerformanceMetrics"
          },
          "actionResults": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActionResult"
            }
          },
          "tabs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "IDs of tabs that remain open after the action sequence."
          },
          "analysis": {
            "$ref": "#/components/schemas/Analysis"
          },
          "probe": {
            "type": "boolean"
          },
          "loadTimeMs": {
            "type": "integer",
            "minimum": 0
          },
          "bodyTextLength": {
            "type": "integer",
            "minimum": 0
          },
          "estimate": {
            "$ref": "#/components/schemas/ProbeEstimate"
          }
        }
      },
      "ScreenshotMetadata": {
        "type": "object",
        "properties": {
          "url": {
            "type": [
              "string",
              "null"
            ]
          },
          "format": {
            "type": "string"
          },
          "httpStatus": {
            "type": [
              "integer",
              "null"
            ]
          },
          "viewport": {
            "$ref": "#/components/schemas/Viewport"
          },
          "durationMs": {
            "type": "integer",
            "minimum": 0
          },
          "timing": {
            "type": "object",
            "properties": {
              "totalMs": {
                "type": "integer",
                "minimum": 0
              },
              "navigationMs": {
                "type": "integer",
                "minimum": 0
              },
              "actionMs": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "render": {
            "type": "object",
            "additionalProperties": true,
            "description": "Applied render controls and any non-fatal render warnings."
          },
          "captureId": {
            "type": "string",
            "format": "uuid"
          },
          "saved": {
            "type": "boolean"
          },
          "retentionDays": {
            "type": "integer",
            "enum": [
              7,
              30,
              90,
              365
            ],
            "description": "Effective retention selected for a successful save."
          },
          "captureExpiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Effective expiry time for a successful saved capture."
          },
          "partialResult": {
            "type": "boolean"
          },
          "framesCompleted": {
            "type": "integer",
            "minimum": 0
          },
          "actionsRemaining": {
            "type": "integer",
            "minimum": 0
          },
          "budgetWarning": {
            "type": "string",
            "description": "Present when the action budget was exhausted and remaining steps were skipped. The budget is 24s on the synchronous path and 52s for async, monitor, batch-child and crawl-child work, and the message states the one that applied."
          },
          "syncTip": {
            "type": "string"
          },
          "warning": {
            "type": "string",
            "description": "Primary non-fatal capture warning. Values include network_idle_timeout, navigation_aborted_after_document_load, and access_challenge."
          },
          "warningDetail": {
            "type": "string"
          },
          "warnings": {
            "type": "array",
            "description": "All non-fatal capture warnings in detection order. The scalar warning and warningDetail fields retain the primary warning for backward compatibility.",
            "items": {
              "type": "object",
              "required": [
                "code",
                "detail"
              ],
              "properties": {
                "code": {
                  "type": "string"
                },
                "detail": {
                  "type": "string"
                }
              }
            }
          },
          "accessChallenge": {
            "type": "object",
            "description": "Present when the rendered document strongly resembles a target-side access or anti-bot verification page. Detection is advisory and the artifact is still returned.",
            "required": [
              "detected",
              "signals"
            ],
            "properties": {
              "detected": {
                "type": "boolean"
              },
              "provider": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "signals": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "ignoredFields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Top-level request fields this API does not understand, echoed back so a misspelled option is visible. Unknown fields remain accepted and ignored so that existing requests stay valid — but an ignored option changes both what you receive and what you are charged, so it is named here. Absent when every field was recognised."
          },
          "forceState": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ForceStateResult"
            },
            "description": "One entry per forceState requested, reporting whether it was applied. Present only when forceState was sent. An identical-looking capture with applied:false and reason SELECTOR_NOT_MATCHED means the element was never found."
          },
          "credits": {
            "$ref": "#/components/schemas/CaptureCredits"
          }
        }
      },
      "Viewport": {
        "type": "object",
        "required": [
          "width",
          "height"
        ],
        "properties": {
          "width": {
            "type": "integer"
          },
          "height": {
            "type": "integer"
          },
          "isMobile": {
            "type": "boolean"
          },
          "deviceScaleFactor": {
            "type": "number"
          }
        }
      },
      "MarkdownMetadata": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "finalUrl": {
            "type": "string"
          },
          "wordCount": {
            "type": "integer",
            "minimum": 0
          },
          "charCount": {
            "type": "integer",
            "minimum": 0
          },
          "estimatedTokens": {
            "type": "integer",
            "minimum": 0
          },
          "contentQuality": {
            "type": "string",
            "description": "Heuristic extraction quality: empty means zero extracted words; low_text means 1-149 words. Callers must still detect target-side blocks and interstitials.",
            "enum": [
              "ok",
              "likely_blocked",
              "empty",
              "low_text",
              "too_large"
            ]
          },
          "ogTitle": {
            "type": "string",
            "description": "og:title, empty when the page declares none."
          },
          "ogDescription": {
            "type": "string",
            "description": "og:description, empty when the page declares none."
          },
          "ogImage": {
            "type": "string",
            "description": "Absolute og:image URL, empty when the page declares none."
          }
        }
      },
      "ExtractedLink": {
        "type": "object",
        "required": [
          "text",
          "href"
        ],
        "properties": {
          "text": {
            "type": "string"
          },
          "href": {
            "type": "string"
          }
        }
      },
      "InteractiveNode": {
        "type": "object",
        "description": "One interactive element, as an agent would need to see it. `text` is the ACCESSIBLE NAME — the string assistive technology would announce — resolved in the order visible text, aria-label, aria-labelledby, value, title, placeholder, alt. Before 2026-08-18 only visible text was read, so an icon-only button carrying a correct aria-label came back anonymous.",
        "properties": {
          "id": {
            "type": [
              "integer",
              "string"
            ]
          },
          "type": {
            "type": "string",
            "description": "The element's tag name."
          },
          "role": {
            "type": [
              "string",
              "null"
            ],
            "description": "The declared role, or the implicit one resolved from the tag (button, link, checkbox, radio, combobox, textbox)."
          },
          "roleSource": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "explicit",
              "implicit",
              null
            ],
            "description": "Whether the page declared the role or it was resolved from the tag."
          },
          "text": {
            "type": "string",
            "description": "The accessible name, truncated to 120 characters."
          },
          "nameSource": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "text",
              "aria-label",
              "aria-labelledby",
              "value",
              "title",
              "placeholder",
              "alt",
              null
            ],
            "description": "Where the name came from. An empty name with a null source is a genuinely unlabelled control — an accessibility defect on the page."
          },
          "disabled": {
            "type": "boolean",
            "description": "Disabled by the attribute or by aria-disabled."
          },
          "expanded": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "aria-expanded, or null when the element does not declare it."
          },
          "pressed": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "aria-pressed, or null when the element does not declare it."
          },
          "placeholder": {
            "type": [
              "string",
              "null"
            ]
          },
          "href": {
            "type": [
              "string",
              "null"
            ]
          },
          "selector": {
            "type": "string"
          },
          "box": {
            "$ref": "#/components/schemas/BoundingBox"
          }
        }
      },
      "PerformanceMetrics": {
        "type": "object",
        "properties": {
          "fcp": {
            "type": "number"
          },
          "lcp": {
            "type": "number"
          },
          "ttfb": {
            "type": "number"
          },
          "cls": {
            "type": "number"
          }
        }
      },
      "ProbeEstimate": {
        "type": "object",
        "properties": {
          "remainingBudgetMs": {
            "type": "integer"
          },
          "safeScrollActions": {
            "type": "integer"
          },
          "safeClickActions": {
            "type": "integer"
          },
          "safeTypeActionsAt20Chars": {
            "type": "integer"
          },
          "warning": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ActionResult": {
        "type": "object",
        "required": [
          "index",
          "action",
          "status",
          "durationMs"
        ],
        "properties": {
          "index": {
            "type": "integer",
            "minimum": 0
          },
          "action": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "passed",
              "failed",
              "skipped"
            ]
          },
          "durationMs": {
            "type": "integer",
            "minimum": 0
          },
          "tabId": {
            "type": "string"
          },
          "target": {
            "type": [
              "string",
              "null"
            ]
          },
          "code": {
            "type": "string"
          },
          "error": {
            "type": "string"
          },
          "details": {}
        }
      },
      "ResolvedLocator": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "css",
              "xpath",
              "text",
              "role",
              "label",
              "placeholder",
              "id",
              "name",
              "testId",
              "coordinates"
            ]
          },
          "value": {}
        }
      },
      "ActionError": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "Analysis": {
        "type": "object",
        "description": "Structured rich analysis is available on every JSON response mode, including grid and skeleton captures.",
        "properties": {
          "semanticSnapshot": {
            "$ref": "#/components/schemas/SemanticSnapshotOutput"
          },
          "diagnostics": {
            "$ref": "#/components/schemas/Diagnostics"
          },
          "extraction": {
            "$ref": "#/components/schemas/ExtractionResult"
          },
          "cleanup": {
            "$ref": "#/components/schemas/CleanupReport"
          }
        }
      },
      "SemanticSnapshot": {
        "type": "object",
        "required": [
          "version",
          "nodes",
          "frames"
        ],
        "properties": {
          "version": {
            "type": "integer",
            "description": "Versioned snapshot format identifier."
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "detail": {
            "type": "string",
            "enum": [
              "summary",
              "full"
            ]
          },
          "document": {
            "$ref": "#/components/schemas/SnapshotDocument"
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SemanticNode"
            }
          },
          "frames": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FrameMetadata"
            }
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "SemanticSnapshotOutput": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/SemanticSnapshot"
          },
          {
            "type": "object",
            "properties": {
              "beforeActions": {
                "$ref": "#/components/schemas/SemanticSnapshot"
              },
              "afterActions": {
                "$ref": "#/components/schemas/SemanticSnapshot"
              }
            }
          }
        ]
      },
      "SemanticNode": {
        "type": "object",
        "required": [
          "id",
          "tag",
          "visible",
          "box",
          "selectorBundles"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Per-snapshot evidence ID. It is not a cross-request action locator."
          },
          "stableKey": {
            "type": "string"
          },
          "tag": {
            "type": "string"
          },
          "role": {
            "type": [
              "string",
              "null"
            ]
          },
          "accessibleName": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "attributes": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Allowed, non-sensitive attributes only."
          },
          "form": {
            "$ref": "#/components/schemas/FormState"
          },
          "parentId": {
            "type": [
              "string",
              "null"
            ]
          },
          "childIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "visible": {
            "type": "boolean"
          },
          "inViewport": {
            "type": "boolean"
          },
          "box": {
            "$ref": "#/components/schemas/BoundingBox"
          },
          "screenshotBox": {
            "$ref": "#/components/schemas/BoundingBox",
            "description": "Coordinates in screenshot pixels."
          },
          "normalizedBox": {
            "$ref": "#/components/schemas/BoundingBox",
            "description": "Box normalized to the current viewport, using fractional coordinates."
          },
          "normalizedScreenshotBox": {
            "$ref": "#/components/schemas/NormalizedCoordinateBox",
            "description": "Box normalized to the returned screenshot's 0-1 coordinate system."
          },
          "viewportIntersection": {
            "$ref": "#/components/schemas/ViewportIntersection"
          },
          "zIndex": {
            "type": [
              "integer",
              "null"
            ]
          },
          "clickable": {
            "type": "boolean"
          },
          "obscuredBy": {
            "type": [
              "string",
              "null"
            ],
            "description": "A redacted description of the element returned by elementFromPoint, when safe to report."
          },
          "selectorBundles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SelectorCandidate"
            }
          },
          "iframe": {
            "$ref": "#/components/schemas/IframeNodeMetadata"
          }
        }
      },
      "SnapshotDocument": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "viewport": {
            "$ref": "#/components/schemas/SnapshotViewport"
          }
        }
      },
      "SnapshotViewport": {
        "type": "object",
        "properties": {
          "width": {
            "type": "integer"
          },
          "height": {
            "type": "integer"
          },
          "devicePixelRatio": {
            "type": "number"
          }
        }
      },
      "IframeNodeMetadata": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "src": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "accessible": {
            "type": "boolean"
          }
        }
      },
      "InputState": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "checked": {
            "type": "boolean"
          },
          "disabled": {
            "type": "boolean"
          },
          "selected": {
            "type": "boolean"
          },
          "required": {
            "type": "boolean"
          },
          "readOnly": {
            "type": "boolean"
          },
          "multiple": {
            "type": "boolean"
          }
        }
      },
      "FormState": {
        "type": "object",
        "description": "Form-control state. Field values are intentionally omitted and valueRedacted is true when a control value existed.",
        "properties": {
          "checked": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "disabled": {
            "type": "boolean"
          },
          "selected": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "required": {
            "type": "boolean"
          },
          "readOnly": {
            "type": "boolean"
          },
          "valid": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "validationMessage": {
            "type": "string"
          },
          "valueRedacted": {
            "type": "boolean"
          }
        }
      },
      "ValidationState": {
        "type": "object",
        "properties": {
          "valid": {
            "type": "boolean"
          },
          "validationMessage": {
            "type": "string"
          },
          "willValidate": {
            "type": "boolean"
          }
        }
      },
      "BoundingBox": {
        "type": "object",
        "required": [
          "x",
          "y",
          "width",
          "height"
        ],
        "properties": {
          "x": {
            "type": "number"
          },
          "y": {
            "type": "number"
          },
          "width": {
            "type": "number",
            "minimum": 0
          },
          "height": {
            "type": "number",
            "minimum": 0
          },
          "viewportX": {
            "type": "number"
          },
          "viewportY": {
            "type": "number"
          },
          "screenshotX": {
            "type": "number"
          },
          "screenshotY": {
            "type": "number"
          },
          "screenshotWidth": {
            "type": "number",
            "minimum": 0
          },
          "screenshotHeight": {
            "type": "number",
            "minimum": 0
          },
          "normalizedX": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "normalizedY": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "normalizedWidth": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "normalizedHeight": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        }
      },
      "NormalizedCoordinateBox": {
        "type": "object",
        "required": [
          "x",
          "y",
          "width",
          "height"
        ],
        "properties": {
          "x": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "y": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "width": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "height": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        }
      },
      "NormalizedBox": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BoundingBox"
          }
        ],
        "description": "Bounding box normalized to 0-1 screenshot coordinates."
      },
      "ViewportIntersection": {
        "type": "object",
        "properties": {
          "intersects": {
            "type": "boolean"
          },
          "ratio": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        }
      },
      "SelectorCandidate": {
        "type": "object",
        "required": [
          "type",
          "value",
          "score",
          "matches"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "css",
              "xpath",
              "text",
              "role",
              "id",
              "name",
              "testId",
              "label",
              "placeholder"
            ]
          },
          "value": {},
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "matches": {
            "type": "integer",
            "minimum": 0
          },
          "unique": {
            "type": "boolean",
            "description": "Derived from matches === 1 when included."
          },
          "brittleness": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high"
            ]
          },
          "reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "FrameMetadata": {
        "type": "object",
        "required": [
          "url",
          "sameOrigin",
          "accessible"
        ],
        "properties": {
          "url": {
            "type": "string"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "sameOrigin": {
            "type": "boolean"
          },
          "accessible": {
            "type": "boolean"
          }
        }
      },
      "Diagnostics": {
        "type": "object",
        "description": "Bounded, redacted HAR-like diagnostics. It deliberately omits cookies, authorization, form values, and request/response bodies.",
        "properties": {
          "console": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConsoleEvent"
            }
          },
          "pageErrors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PageError"
            }
          },
          "failedRequests": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FailedRequest"
            }
          },
          "responses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetworkResponse"
            }
          },
          "redirects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Redirect"
            }
          },
          "resources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResourceTiming"
            }
          },
          "summary": {
            "$ref": "#/components/schemas/DiagnosticsSummary"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "ConsoleEvent": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PageError": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "FailedRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "method": {
            "type": "string"
          },
          "resourceType": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        }
      },
      "NetworkResponse": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "method": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "resourceType": {
            "type": "string"
          },
          "fromCache": {
            "type": "boolean"
          }
        }
      },
      "Redirect": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string"
          },
          "to": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          }
        }
      },
      "ResourceTiming": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "initiatorType": {
            "type": "string"
          },
          "duration": {
            "type": "number",
            "minimum": 0
          },
          "transferSize": {
            "type": "integer",
            "minimum": 0
          },
          "encodedBodySize": {
            "type": "integer",
            "minimum": 0
          },
          "decodedBodySize": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "ThirdPartyDomain": {
        "type": "object",
        "properties": {
          "domain": {
            "type": "string"
          },
          "requestCount": {
            "type": "integer",
            "minimum": 0
          },
          "transferSize": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "DiagnosticsSummary": {
        "type": "object",
        "properties": {
          "consoleCount": {
            "type": "integer",
            "minimum": 0
          },
          "pageErrorCount": {
            "type": "integer",
            "minimum": 0
          },
          "failedRequestCount": {
            "type": "integer",
            "minimum": 0
          },
          "responseCount": {
            "type": "integer",
            "minimum": 0
          },
          "resourceCount": {
            "type": "integer",
            "minimum": 0
          },
          "thirdPartyDomains": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "transferBytes": {
            "type": "integer",
            "minimum": 0
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "CleanupReport": {
        "type": "object",
        "properties": {
          "removed": {
            "type": "integer",
            "minimum": 0
          },
          "categories": {
            "type": "object",
            "additionalProperties": {
              "type": "integer",
              "minimum": 0
            }
          }
        }
      },
      "CleanupRemoval": {
        "type": "object",
        "properties": {
          "category": {
            "type": "string",
            "enum": [
              "cookieBanner",
              "ad",
              "chatWidget",
              "newsletterPopup",
              "modalBackdrop",
              "stickyHeader",
              "stickyFooter"
            ]
          },
          "count": {
            "type": "integer",
            "minimum": 0
          },
          "selectors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ExtractionResult": {
        "type": "object",
        "required": [
          "fields"
        ],
        "properties": {
          "fields": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/ExtractedField"
            }
          }
        }
      },
      "ExtractedField": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "found",
              "missing",
              "invalid_selector"
            ]
          },
          "value": {},
          "evidence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExtractionEvidence"
            }
          },
          "sourceNodeIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Semantic snapshot node IDs that supplied extraction evidence, when a snapshot was requested."
          },
          "error": {
            "type": "string"
          }
        }
      },
      "ExtractionEvidence": {
        "type": "object",
        "properties": {
          "nodeId": {
            "type": "string"
          },
          "selector": {
            "type": "string"
          },
          "index": {
            "type": "integer",
            "minimum": 0
          },
          "tag": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "attribute": {
            "type": "string"
          }
        }
      },
      "JobAccepted": {
        "type": "object",
        "required": [
          "status",
          "jobId",
          "pollUrl"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "accepted",
              "pending",
              "processing",
              "retrying",
              "done",
              "error",
              "cancel_requested",
              "cancelled"
            ]
          },
          "jobId": {
            "type": "string",
            "format": "uuid"
          },
          "pollUrl": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "replayed": {
            "type": "boolean",
            "description": "true when an identical Idempotency-Key submission returned the original durable job."
          },
          "estimatedMs": {
            "type": [
              "string",
              "integer"
            ]
          },
          "autoPromoted": {
            "type": "boolean",
            "description": "true when a synchronous rich response was automatically moved to durable execution."
          },
          "metadata": {
            "type": "object",
            "properties": {
              "autoPromotedAsync": {
                "type": "boolean",
                "description": "true when the service promoted a would-be synchronous response to a durable job."
              }
            }
          },
          "message": {
            "type": "string"
          }
        }
      },
      "JobStatus": {
        "type": "object",
        "required": [
          "status",
          "jobId"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/JobState"
          },
          "jobId": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "startedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "doneAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "message": {
            "type": "string"
          },
          "result": {
            "$ref": "#/components/schemas/ScreenshotResponse"
          },
          "error": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "$ref": "#/components/schemas/JobError"
              }
            ]
          },
          "code": {
            "type": "string"
          },
          "suggestions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "recovered": {
            "type": "boolean"
          },
          "cancellationRequestedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "accepted": {
            "type": "boolean",
            "description": "Present on a successful cooperative cancellation response."
          }
        }
      },
      "JobState": {
        "type": "string",
        "enum": [
          "pending",
          "processing",
          "retrying",
          "done",
          "error",
          "cancel_requested",
          "cancelled"
        ]
      },
      "JobError": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "JobMetadata": {
        "type": "object",
        "required": [
          "jobId",
          "status"
        ],
        "properties": {
          "jobId": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": [
              "capture",
              "batch",
              "crawl",
              "webhook_replay"
            ]
          },
          "status": {
            "$ref": "#/components/schemas/JobState"
          },
          "parentJobId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "startedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "doneAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "timing": {
            "$ref": "#/components/schemas/TimingBreakdown"
          },
          "result": {},
          "resultSummary": {
            "type": "object",
            "additionalProperties": true
          },
          "counts": {
            "$ref": "#/components/schemas/ChildCounts"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "TimingBreakdown": {
        "type": "object",
        "properties": {
          "queuedMs": {
            "type": "integer",
            "minimum": 0
          },
          "browserMs": {
            "type": "integer",
            "minimum": 0
          },
          "uploadMs": {
            "type": "integer",
            "minimum": 0
          },
          "webhookMs": {
            "type": "integer",
            "minimum": 0
          },
          "totalMs": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "CollectionPagination": {
        "type": "object",
        "required": [
          "total",
          "limit",
          "offset"
        ],
        "properties": {
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          },
          "offset": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "SavedCaptureListItem": {
        "type": "object",
        "required": [
          "id",
          "artifactKinds"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "targetUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "format": {
            "type": [
              "string",
              "null"
            ]
          },
          "mode": {
            "type": [
              "string",
              "null"
            ]
          },
          "width": {
            "type": [
              "integer",
              "null"
            ]
          },
          "height": {
            "type": [
              "integer",
              "null"
            ]
          },
          "isMobile": {
            "type": "boolean"
          },
          "fullPage": {
            "type": "boolean"
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "retentionDays": {
            "type": [
              "integer",
              "null"
            ]
          },
          "artifactKinds": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "screenshot",
                "markdown",
                "nodes",
                "result"
              ]
            }
          }
        }
      },
      "SavedCaptureListResponse": {
        "type": "object",
        "required": [
          "captures",
          "pagination"
        ],
        "properties": {
          "captures": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SavedCaptureListItem"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/CollectionPagination"
          }
        }
      },
      "JobListItem": {
        "type": "object",
        "required": [
          "jobId",
          "status",
          "kind",
          "counts",
          "createdAt"
        ],
        "properties": {
          "jobId": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "$ref": "#/components/schemas/JobState"
          },
          "kind": {
            "type": "string"
          },
          "parentJobId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "startedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "cancellationRequestedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "counts": {
            "$ref": "#/components/schemas/ChildCounts"
          },
          "timing": {
            "$ref": "#/components/schemas/TimingBreakdown"
          },
          "requestSummary": {
            "type": "object",
            "additionalProperties": true
          },
          "resultSummary": {
            "type": "object",
            "additionalProperties": true
          },
          "error": {
            "$ref": "#/components/schemas/JobError"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "JobListResponse": {
        "type": "object",
        "required": [
          "jobs",
          "pagination"
        ],
        "properties": {
          "jobs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JobListItem"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/CollectionPagination"
          }
        }
      },
      "CaptureLookupResponse": {
        "type": "object",
        "required": [
          "status",
          "capture"
        ],
        "properties": {
          "status": {
            "type": "string",
            "const": "success"
          },
          "capture": {
            "$ref": "#/components/schemas/SavedCapture"
          }
        }
      },
      "SavedCapture": {
        "type": "object",
        "required": [
          "id",
          "expiresAt",
          "artifacts"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "targetUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "format": {
            "type": "string"
          },
          "mode": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Effective retained-capture expiry for a finite new save. At or after this time the route returns 404. Null means a historic legacy row with permanent retention."
          },
          "retentionDays": {
            "type": [
              "integer",
              "null"
            ],
            "enum": [
              7,
              30,
              90,
              365,
              null
            ],
            "description": "Effective finite retention duration for a new save. Null for a historic legacy permanent row."
          },
          "artifacts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SavedCaptureArtifact"
            }
          }
        }
      },
      "SavedCaptureArtifact": {
        "type": "object",
        "required": [
          "kind",
          "contentType",
          "expiresAt",
          "downloadUrl",
          "downloadUrlExpiresAt"
        ],
        "properties": {
          "kind": {
            "type": "string"
          },
          "contentType": {
            "type": "string"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "The finite saved-capture retention expiry, not the signed-URL expiry. Null for an artifact of a historic legacy permanent capture."
          },
          "downloadUrl": {
            "type": "string",
            "format": "uri",
            "description": "Signed URL, capped at one hour and clamped not to outlive a finite-retention capture. There is no separate S3-key field, but this URL can contain storage-path information. Treat it as a secret capability URL."
          },
          "downloadUrlExpiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "When this signed URL stops working. It is at most one hour after issuance and, for finite retention, never later than expiresAt."
          }
        }
      },
      "BatchRequest": {
        "type": "object",
        "required": [
          "requests"
        ],
        "properties": {
          "requests": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/BatchItemRequest"
            }
          },
          "metadata": {
            "type": "object",
            "maxProperties": 50,
            "additionalProperties": {}
          },
          "callbackUrl": {
            "type": "string",
            "format": "uri",
            "pattern": "^https://",
            "maxLength": 4096,
            "description": "Public HTTPS callback endpoint checked against private, reserved, and metadata addresses before acceptance and delivery."
          }
        }
      },
      "CrawlRequest": {
        "type": "object",
        "required": [
          "seedUrl",
          "allowedOrigins"
        ],
        "properties": {
          "seedUrl": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS starting URL."
          },
          "allowedOrigins": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "pattern": "^https://"
            },
            "description": "Explicit HTTPS origin allowlist. Include every external origin the crawler may follow."
          },
          "includePatterns": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "type": "string",
              "maxLength": 2048
            }
          },
          "excludePatterns": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "type": "string",
              "maxLength": 2048
            }
          },
          "maxDepth": {
            "type": "integer",
            "minimum": 0,
            "maximum": 5,
            "default": 3
          },
          "maxPages": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 100
          },
          "respectRobots": {
            "type": "boolean",
            "const": true,
            "default": true,
            "description": "robots.txt is always respected for crawls; false is not accepted."
          },
          "capture": {
            "$ref": "#/components/schemas/CrawlCaptureOptions"
          },
          "metadata": {
            "type": "object",
            "maxProperties": 50,
            "additionalProperties": {}
          },
          "callbackUrl": {
            "type": "string",
            "format": "uri",
            "pattern": "^https://",
            "maxLength": 4096,
            "description": "Public HTTPS callback endpoint checked against private, reserved, and metadata addresses before acceptance and delivery."
          }
        }
      },
      "CrawlCaptureOptions": {
        "type": "object",
        "description": "Per-page screenshot options. url, html, async, callbackUrl, callbackSecret, and save are owned by the crawl job and are not accepted here.",
        "properties": {
          "format": {
            "type": "string",
            "enum": [
              "png",
              "jpeg",
              "webp",
              "pdf"
            ]
          },
          "fullPage": {
            "type": "boolean"
          },
          "extractMarkdown": {
            "type": "boolean"
          },
          "semanticSnapshot": {
            "$ref": "#/components/schemas/SemanticSnapshotOptions"
          },
          "diagnostics": {
            "$ref": "#/components/schemas/DiagnosticsOptions"
          },
          "render": {
            "$ref": "#/components/schemas/RenderOptions"
          },
          "cleanup": {
            "$ref": "#/components/schemas/CleanupOptions"
          },
          "extract": {
            "$ref": "#/components/schemas/ExtractOptions"
          }
        }
      },
      "ParentJobAccepted": {
        "type": "object",
        "required": [
          "status",
          "jobId",
          "pollUrl",
          "kind"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "accepted",
              "pending",
              "processing",
              "retrying",
              "done",
              "error",
              "cancel_requested",
              "cancelled"
            ]
          },
          "jobId": {
            "type": "string",
            "format": "uuid"
          },
          "pollUrl": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "batch",
              "crawl"
            ]
          },
          "counts": {
            "$ref": "#/components/schemas/ChildCounts"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "message": {
            "type": "string"
          },
          "replayed": {
            "type": "boolean",
            "description": "Present and true when an Idempotency-Key matched an existing workflow and this response replays it rather than creating a new one."
          }
        }
      },
      "ParentJobStatus": {
        "description": "Status of a batch or crawl parent job. Per-item progress is reported by `items`; the aggregate counts are on `counts`, inherited from JobMetadata.",
        "allOf": [
          {
            "$ref": "#/components/schemas/JobMetadata"
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "batch",
                  "crawl"
                ]
              },
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ParentJobItem"
                }
              }
            }
          }
        ]
      },
      "ParentJobItem": {
        "type": "object",
        "description": "One row of the parent job's `job_items`: a submitted batch request or a crawled page.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "childJobId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Durable child job ID when this item has been enqueued; use GET /job/{jobId} to poll it."
          },
          "sequence": {
            "type": "integer",
            "minimum": 1
          },
          "type": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/JobState"
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          },
          "canonicalUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "depth": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "startedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "error": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          },
          "resultSummary": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "ChildCounts": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "pending": {
            "type": "integer",
            "minimum": 0
          },
          "processing": {
            "type": "integer",
            "minimum": 0
          },
          "done": {
            "type": "integer",
            "minimum": 0
          },
          "completed": {
            "type": "integer",
            "minimum": 0
          },
          "succeeded": {
            "type": "integer",
            "minimum": 0
          },
          "error": {
            "type": "integer",
            "minimum": 0
          },
          "failed": {
            "type": "integer",
            "minimum": 0
          },
          "cancelled": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "WebhookReplayAccepted": {
        "type": "object",
        "required": [
          "status",
          "deliveryId",
          "attemptId"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "accepted",
              "pending"
            ]
          },
          "deliveryId": {
            "type": "string",
            "format": "uuid"
          },
          "attemptId": {
            "type": "string",
            "format": "uuid"
          },
          "scheduledAt": {
            "type": "string",
            "format": "date-time"
          },
          "replayed": {
            "type": "boolean",
            "description": "true when an identical Idempotency-Key request returned an already queued replay attempt."
          },
          "accepted": {
            "type": "boolean"
          },
          "reason": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "description": "Stable machine-readable classification. Every error response carries one: ordinary field validation uses VALIDATION_FAILED, and anything a caller might reasonably branch on separately has its own code. The complete list, with the status each accompanies, is enumerated in components.x-error-codes. Plan-only restrictions use PLAN_FEATURE_UNAVAILABLE; FEATURE_NOT_ENABLED identifies a global product emergency pause or a trusted-JavaScript account-entitlement restriction. Capture-side refusals that were previously uncaught renderer failures: WAIT_FOR_SELECTOR_TIMEOUT, CAPTURE_SELECTOR_NOT_FOUND, CAPTURE_SELECTOR_FAILED and CAPTURE_TOO_TALL, all 400. A refused target URL carries its own 400 code rather than a generic renderer failure: URL_SCHEME_NOT_ALLOWED (only http and https are dialled), URL_BLOCKED (the target is loopback, private, or otherwise reserved — including IPv6 literals such as [::1] and cloud metadata addresses), URL_UNRESOLVABLE (no public address resolves for the host), and URL_INVALID (not a URL). These are policy denials decided before any navigation, so no request is made to the target. A navigation that fails because of the TARGET, not the request, is a 502 naming which: TARGET_TLS_FAILED (the certificate could not be validated), TARGET_UNREACHABLE (refused, reset, or no route), TOO_MANY_REDIRECTS, TARGET_INVALID_RESPONSE, and TARGET_NAVIGATION_FAILED for anything else the browser refused to load. These are never 500 — the request was well formed and the URL passed admission. A target that simply takes too long is 504 NAVIGATION_TIMEOUT. RENDER_DEADLINE_EXCEEDED is a 504 synchronous-response limit; retry it with async:true. JOB_NOT_FOUND accompanies a 404 for an unknown, expired, or malformed job id. A 429 names which wall was hit: RATE_LIMIT_EXCEEDED (retry after Retry-After), QUOTA_EXCEEDED (add credits or wait for the calendar month), or OVERAGE_CEILING_REACHED (neither; contact support). Codes are SCREAMING_SNAKE without exception: a refusal that originates in the database is mapped onto this vocabulary rather than published in the database's own casing, and an unrecognised one collapses to the route's generic code so the set stays enumerable. A few entries below are reported inside a job's error.code rather than as an HTTP error body; their status column reads 200 because that is the status of the poll that returns them."
          },
          "detail": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          },
          "suggestions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "details": {},
          "upgrade_url": {
            "type": "string",
            "format": "uri",
            "description": "Present only on a PLAN-only refusal, and absent from every platform refusal. A 403 carrying this can be cleared by upgrading; a 403 without it cannot, which is the distinction between PLAN_FEATURE_UNAVAILABLE and codes such as FEATURE_NOT_ENABLED, BROWSER_ISOLATION_REQUIRED and BROWSER_EXECUTION_DENIED. Branch on its presence rather than on the status."
          },
          "existingJobId": {
            "type": "string",
            "format": "uuid",
            "description": "The job already holding the thing this request wanted. Returned with 409 WORKFLOW_ALREADY_ACTIVE (the parent batch or crawl already running for this key) and with 409 IDEMPOTENCY_CONFLICT (the job the reused Idempotency-Key first created). Poll or cancel that job rather than retrying this request, which is refused identically."
          },
          "existingDeliveryId": {
            "type": "string",
            "format": "uuid",
            "description": "The webhook delivery a reused Idempotency-Key first created, returned with 409 IDEMPOTENCY_CONFLICT on a replay request."
          }
        }
      },
      "IdempotencyConflict": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ErrorResponse"
          },
          {
            "type": "object",
            "required": [
              "code"
            ],
            "properties": {
              "code": {
                "type": "string",
                "const": "IDEMPOTENCY_CONFLICT"
              },
              "existingJobId": {
                "type": "string",
                "format": "uuid"
              }
            }
          }
        ]
      },
      "BatchItemRequest": {
        "description": "A single batch item. Identical to ScreenshotRequest except that async, save, callbackUrl, and callbackSecret are owned by the parent workflow and are rejected with 400 when set on an item.",
        "allOf": [
          {
            "$ref": "#/components/schemas/ScreenshotRequest"
          },
          {
            "type": "object",
            "properties": {
              "async": {
                "not": {}
              },
              "save": {
                "not": {}
              },
              "callbackUrl": {
                "not": {}
              },
              "callbackSecret": {
                "not": {}
              }
            }
          }
        ]
      },
      "CreditSummary": {
        "type": "object",
        "description": "Balance, quota, and the price list. Returned by GET /credits, which is never billed.",
        "properties": {
          "credits": {
            "type": "object",
            "properties": {
              "balance": {
                "type": "integer",
                "description": "Prepaid credits available. Never expires, and survives a cancelled subscription."
              },
              "spentThisMonth": {
                "type": "integer",
                "description": "Credits spent since the start of the current calendar month (UTC)."
              }
            }
          },
          "quota": {
            "type": "object",
            "properties": {
              "planId": {
                "type": "string",
                "enum": [
                  "hobby",
                  "pro",
                  "business",
                  "enterprise"
                ]
              },
              "included": {
                "type": "integer",
                "description": "Capture units included per calendar month by the plan."
              },
              "used": {
                "type": "integer"
              },
              "remaining": {
                "type": "integer"
              },
              "periodStart": {
                "type": "string",
                "format": "date-time"
              },
              "resets": {
                "type": "string",
                "description": "Always \"calendar-month (UTC)\", including on an annual subscription."
              }
            }
          },
          "overage": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean",
                "description": "Whether this account may accrue postpaid overage. Hobby is always false for metered overage; prepaid credits may still fund work. Paid accounts can change the stored preference from the dashboard."
              },
              "ceiling": {
                "type": "integer",
                "description": "Total monthly units the subscription may reach including metered overage."
              },
              "used": {
                "type": "integer"
              }
            }
          },
          "rateLimit": {
            "type": "object",
            "properties": {
              "perSecond": {
                "type": "integer",
                "description": "Requests per second. A credit balance never raises this."
              }
            }
          },
          "pricing": {
            "type": "object",
            "description": "What a request costs. Requests are weighted by what they make the browser do.",
            "properties": {
              "base": {
                "type": "integer",
                "description": "Every capture costs at least this."
              },
              "max": {
                "type": "integer",
                "description": "No single request can cost more than this, whatever it combines."
              },
              "surcharges": {
                "type": "object",
                "description": "Added to the base when the named option is used. Not listed means free.",
                "additionalProperties": {
                  "type": "integer"
                }
              },
              "routeSurcharges": {
                "type": "object",
                "description": "Added to the base for provider-backed non-browser routes.",
                "additionalProperties": {
                  "type": "integer"
                }
              },
              "chargeOrder": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Buckets are spent in this order: included quota, then prepaid credits, then metered overage."
              },
              "free": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Requests that are never billed. This is a PRICE, not an entitlement: POST /batch and POST /crawl appear here and require the Business plan or higher. A global product emergency pause can still temporarily hold them; read `capabilities.routes` to learn what this key may call."
              }
            }
          },
          "capabilities": {
            "type": "object",
            "description": "What this key can actually use right now, and why not when it cannot. Reported so a client never has to discover a global product pause, trusted-JavaScript account gate, or unconfigured provider by spending a billed request on it. Normal DOM product access is plan-based; providers are configured per deployment.",
            "properties": {
              "routes": {
                "type": "object",
                "description": "Gated routes, keyed by path. POST /screenshot appears because two platform controls can close browser capture for every key. A route that is absent — every GET and DELETE route, POST /feedback — is available on every plan.",
                "additionalProperties": {
                  "$ref": "#/components/schemas/CapabilityState"
                }
              },
              "captureOptions": {
                "type": "object",
                "description": "Fields of a POST /screenshot body that carry their own gate, keyed by field name. Each rides on a capture, so a platform hold on POST /screenshot is reported here too.",
                "additionalProperties": {
                  "$ref": "#/components/schemas/CapabilityState"
                }
              }
            }
          }
        }
      },
      "CapabilityState": {
        "type": "object",
        "description": "Whether one capability is usable by this key on this deployment. Evaluated with the same predicate, and in the same order, as the refusal the route would return, so it never promises something a route would refuse.",
        "properties": {
          "available": {
            "type": "boolean",
            "description": "True when the plan, relevant trusted-JavaScript entitlement, product-pause state, and this deployment's configuration all allow the call. Not a health check: a configured provider can still be down, or too slow for the synchronous deadline."
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "plan",
              "account_rollout",
              "deployment",
              "platform",
              null
            ],
            "description": "Null when available. plan: an upgrade clears it. account_rollout: a narrow operator-held account entitlement is off (currently trusted JavaScript), so neither upgrading nor retrying changes anything. deployment: no provider is configured for this capability here, so it is unavailable to every key on this deployment, on any plan. platform: a deployment-wide browser safety control or the global product emergency pause is active; browser safety controls refuse before every other gate and neither state is cleared by an upgrade or retry."
          },
          "code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Null when available. Otherwise the error code the route would return: PLAN_FEATURE_UNAVAILABLE, FEATURE_NOT_ENABLED, BROWSER_ISOLATION_REQUIRED, BROWSER_EXECUTION_DENIED, LLM_NOT_CONFIGURED, EMBEDDINGS_NOT_CONFIGURED, AI_PROVIDER_MISCONFIGURED, SEARCH_NOT_CONFIGURED, or SEARCH_PROVIDER_MISCONFIGURED."
          }
        },
        "required": [
          "available",
          "reason",
          "code"
        ]
      },
      "MapRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "pattern": "^https://",
            "maxLength": 4096
          },
          "maxPages": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 50
          },
          "maxDepth": {
            "type": "integer",
            "minimum": 0,
            "maximum": 3,
            "default": 2
          },
          "maxUrls": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 500
          },
          "includeSitemap": {
            "type": "boolean",
            "default": true
          },
          "discoverLinks": {
            "type": "boolean",
            "default": true
          },
          "includePaths": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string",
              "pattern": "^/",
              "maxLength": 2048
            }
          },
          "excludePaths": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string",
              "pattern": "^/",
              "maxLength": 2048
            }
          },
          "allowExternalLinks": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "MapResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "seedUrl": {
            "type": "string",
            "format": "uri"
          },
          "urls": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "source": {
                  "type": "string"
                },
                "depth": {
                  "type": [
                    "integer",
                    "null"
                  ]
                }
              }
            }
          },
          "counts": {
            "type": "object",
            "properties": {
              "urls": {
                "type": "integer"
              },
              "pagesFetched": {
                "type": "integer"
              },
              "sitemapsFetched": {
                "type": "integer"
              }
            }
          },
          "truncated": {
            "type": "boolean"
          },
          "limits": {
            "type": "object",
            "properties": {
              "maxPages": {
                "type": "integer"
              },
              "maxDepth": {
                "type": "integer"
              },
              "maxUrls": {
                "type": "integer"
              }
            }
          },
          "billing": {
            "$ref": "#/components/schemas/BillingInfo"
          },
          "metadata": {
            "type": "object",
            "description": "Present only when the request needs something reported back. Currently carries ignoredFields.",
            "properties": {
              "ignoredFields": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Top-level request fields this route does not understand. They were ignored, not rejected — existing requests stay valid — but an ignored field changes the answer without changing the price, so it is named here. A misspelling such as maxChunk for maxChunks appears in this array. At most 20 are listed."
              }
            }
          }
        }
      },
      "ExtractRequest": {
        "type": "object",
        "required": [
          "prompt",
          "schema"
        ],
        "anyOf": [
          {
            "required": [
              "url"
            ]
          },
          {
            "required": [
              "content"
            ]
          },
          {
            "required": [
              "html"
            ]
          }
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 4096
          },
          "content": {
            "type": "string",
            "maxLength": 300000
          },
          "html": {
            "type": "string",
            "maxLength": 1000000
          },
          "prompt": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000
          },
          "schema": {
            "type": "object",
            "maxProperties": 100,
            "description": "A JSON Schema object describing the expected output. domscout enforces a declared SUBSET of JSON Schema: type, enum, const, properties, required, additionalProperties, minProperties, maxProperties, items, minItems, maxItems, uniqueItems, minLength, maxLength, pattern, minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, anyOf, oneOf. The annotations title, description, default, examples, $comment and $schema are accepted and carry no constraint. Any other keyword — including format, $ref, allOf, not and patternProperties — is rejected with a 400 rather than accepted and ignored, so a 200 means every constraint supplied was checked. Maximum nesting depth is 12. A `pattern` is a caller-supplied regular expression run against model output and is refused at 400 if it exceeds 512 characters or its structure permits catastrophic backtracking."
          },
          "model": {
            "type": "string",
            "maxLength": 128,
            "description": "Optional. When present it must equal the model this deployment is configured to run (the value echoed as `model` in a successful response); any other value is refused with 400 VALIDATION_FAILED before a provider is called. The route's credit price does not depend on the model, so the model is the deployment's choice, not the caller's."
          }
        }
      },
      "ExtractResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "data": {
            "type": "object"
          },
          "source": {
            "type": "object",
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "characters": {
                "type": "integer"
              }
            }
          },
          "model": {
            "type": "string"
          },
          "usage": {
            "type": [
              "object",
              "null"
            ]
          },
          "billing": {
            "$ref": "#/components/schemas/BillingInfo"
          },
          "metadata": {
            "type": "object",
            "description": "Present only when the request needs something reported back. Currently carries ignoredFields.",
            "properties": {
              "ignoredFields": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Top-level request fields this route does not understand. They were ignored, not rejected — existing requests stay valid — but an ignored field changes the answer without changing the price, so it is named here. A misspelling such as maxChunk for maxChunks appears in this array. At most 20 are listed."
              }
            }
          }
        }
      },
      "SearchRequest": {
        "type": "object",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1000
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "default": 5
          },
          "scrape": {
            "type": "boolean",
            "default": true
          },
          "maxChars": {
            "type": "integer",
            "minimum": 1000,
            "maximum": 40000,
            "default": 20000
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          },
          "scraped": {
            "type": "integer"
          },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "position": {
                  "type": "integer"
                },
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "snippet": {
                  "type": "string"
                },
                "content": {
                  "type": "string"
                },
                "scrape": {
                  "type": "object"
                }
              }
            }
          },
          "billing": {
            "$ref": "#/components/schemas/BillingInfo"
          },
          "metadata": {
            "type": "object",
            "description": "Present only when the request needs something reported back. Currently carries ignoredFields.",
            "properties": {
              "ignoredFields": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Top-level request fields this route does not understand. They were ignored, not rejected — existing requests stay valid — but an ignored field changes the answer without changing the price, so it is named here. A misspelling such as maxChunk for maxChunks appears in this array. At most 20 are listed."
              }
            }
          }
        }
      },
      "IndexRequest": {
        "type": "object",
        "anyOf": [
          {
            "required": [
              "url"
            ]
          },
          {
            "required": [
              "content"
            ]
          },
          {
            "required": [
              "html"
            ]
          }
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 4096
          },
          "sourceUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 4096
          },
          "content": {
            "type": "string",
            "maxLength": 300000
          },
          "html": {
            "type": "string",
            "maxLength": 1000000
          },
          "title": {
            "type": "string",
            "maxLength": 512
          },
          "metadata": {
            "type": "object",
            "maxProperties": 50
          },
          "chunkSize": {
            "type": "integer",
            "minimum": 500,
            "maximum": 8000,
            "default": 4000
          },
          "chunkOverlap": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000,
            "default": 400
          },
          "maxChunks": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 500
          }
        }
      },
      "IndexResponse": {
        "type": "object",
        "properties": {
          "documentId": {
            "type": "string",
            "format": "uuid"
          },
          "sourceUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "chunks": {
            "type": "integer"
          },
          "embeddingModel": {
            "type": "string"
          },
          "billing": {
            "$ref": "#/components/schemas/BillingInfo"
          },
          "metadata": {
            "type": "object",
            "description": "Present only when the request needs something reported back. Currently carries ignoredFields.",
            "properties": {
              "ignoredFields": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Top-level request fields this route does not understand. They were ignored, not rejected — existing requests stay valid — but an ignored field changes the answer without changing the price, so it is named here. A misspelling such as maxChunk for maxChunks appears in this array. At most 20 are listed."
              }
            }
          }
        }
      },
      "SemanticSearchRequest": {
        "type": "object",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20,
            "default": 10
          },
          "documentId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "SemanticSearchResponse": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          },
          "embeddingModel": {
            "type": "string"
          },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "documentId": {
                  "type": "string",
                  "format": "uuid"
                },
                "sourceUrl": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "title": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "chunkIndex": {
                  "type": "integer"
                },
                "content": {
                  "type": "string"
                },
                "similarity": {
                  "type": "number"
                },
                "metadata": {
                  "type": "object"
                }
              }
            }
          },
          "billing": {
            "$ref": "#/components/schemas/BillingInfo"
          },
          "metadata": {
            "type": "object",
            "description": "Present only when the request needs something reported back. Currently carries ignoredFields.",
            "properties": {
              "ignoredFields": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Top-level request fields this route does not understand. They were ignored, not rejected — existing requests stay valid — but an ignored field changes the answer without changing the price, so it is named here. A misspelling such as maxChunk for maxChunks appears in this array. At most 20 are listed."
              }
            }
          }
        }
      },
      "BillingInfo": {
        "type": "object",
        "properties": {
          "credits": {
            "type": "integer"
          },
          "chargedTo": {
            "type": [
              "string",
              "null"
            ]
          },
          "remaining": {
            "type": [
              "integer",
              "null"
            ]
          },
          "quotaRemaining": {
            "type": [
              "integer",
              "null"
            ]
          }
        }
      },
      "FeedbackRequest": {
        "type": "object",
        "required": [
          "message"
        ],
        "additionalProperties": false,
        "properties": {
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 8000,
            "description": "What happened, or what would help. The only required field."
          },
          "type": {
            "type": "string",
            "enum": [
              "bug",
              "error_report",
              "docs_gap",
              "feature_request",
              "praise",
              "other"
            ],
            "default": "other",
            "description": "Unrecognised values become \"other\" rather than being rejected."
          },
          "severity": {
            "type": "string",
            "enum": [
              "blocking",
              "major",
              "minor",
              "info"
            ],
            "default": "info",
            "description": "\"blocking\" means you could not complete the task at all."
          },
          "requestId": {
            "type": "string",
            "maxLength": 255,
            "description": "The X-Request-Id of the request this is about. When present, the server attaches its own record of that request — status, error, latency, format — so you need not restate them."
          },
          "endpoint": {
            "type": "string",
            "maxLength": 256,
            "description": "e.g. \"POST /screenshot\"."
          },
          "expected": {
            "type": "string",
            "maxLength": 2000,
            "description": "What you expected to happen."
          },
          "actual": {
            "type": "string",
            "maxLength": 2000,
            "description": "What happened instead."
          },
          "agent": {
            "type": "object",
            "description": "Who is reporting: model, framework, version. Self-declared, used only to spot patterns across reports, never for authorization. Up to 10 string/number/boolean values.",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean"
              ]
            }
          }
        }
      },
      "FeedbackAccepted": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "received"
            ]
          },
          "feedbackId": {
            "type": "string",
            "format": "uuid"
          },
          "charged": {
            "type": "boolean",
            "enum": [
              false
            ],
            "description": "Always false. Feedback is never billed."
          },
          "creditCost": {
            "type": "integer",
            "enum": [
              0
            ]
          },
          "reportsToday": {
            "type": "integer",
            "description": "Reports from this account in the last 24 hours, including this one."
          },
          "message": {
            "type": "string"
          },
          "normalized": {
            "type": "array",
            "description": "Fields that were stored differently from how they were sent. This endpoint deliberately coerces rather than rejecting — an unrecognised `type` is filed as \"other\", an unrecognised `severity` as \"info\", and a message longer than 8000 characters is truncated — because refusing a bug report over a bad enum value discards the report. Absent when nothing was changed.",
            "items": {
              "type": "object",
              "properties": {
                "field": {
                  "type": "string"
                },
                "supplied": {
                  "type": "string"
                },
                "recordedAs": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Monitor": {
        "type": "object",
        "description": "A monitor as the API presents it. The signing secret is never included: only creation and rotation responses carry it, and no API read returns it. The dashboard can reveal it to the account owner.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "targetUrl": {
            "type": "string",
            "format": "uri"
          },
          "captureParams": {
            "type": "object",
            "description": "The capture options every run uses. Restricted to an allow-list; injectJS is not among them, so a scheduled unattended render can never carry caller-supplied JavaScript."
          },
          "intervalMinutes": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused"
            ]
          },
          "checks": {
            "type": "object",
            "properties": {
              "markdown": {
                "type": "boolean"
              },
              "links": {
                "type": "boolean"
              },
              "title": {
                "type": "boolean"
              },
              "statusCode": {
                "type": "boolean"
              },
              "dom": {
                "type": "boolean"
              }
            }
          },
          "domIgnoreSelectors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "domIgnoreAttributes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "domIgnoreTextPatterns": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Checked for catastrophic backtracking at save time, because the worker applies them under a CPU budget on every run."
          },
          "domPositionTolerancePx": {
            "type": "integer"
          },
          "notifyWebhookUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "lastRunAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "lastRunStatus": {
            "type": [
              "string",
              "null"
            ]
          },
          "nextRunAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "consecutiveErrors": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "MonitorRun": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "monitorId": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string"
          },
          "changeDetected": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "changedFields": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "domChanged": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "domChangeSummary": {
            "type": [
              "object",
              "null"
            ]
          },
          "captureId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "diffId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "latencyMs": {
            "type": [
              "integer",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "startedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "description": "A signed callback this account queued, and how it went. The delivered payload, the endpoint's response body and the per-delivery signing secret are never included: this route answers whether the callback arrived, not what was in it.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The deliveryId to pass to the replay route."
          },
          "eventType": {
            "type": "string"
          },
          "targetUrl": {
            "type": "string",
            "format": "uri"
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "signed": {
            "type": "boolean"
          },
          "success": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "attemptCount": {
            "type": "integer"
          },
          "maxAttempts": {
            "type": [
              "integer",
              "null"
            ]
          },
          "responseStatus": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The HTTP status your endpoint returned."
          },
          "latencyMs": {
            "type": [
              "integer",
              "null"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "nextAttemptAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "lastAttemptAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "endpointId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "jobId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "monitorRunId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "replayOfDeliveryId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "payloadSummary": {
            "type": [
              "object",
              "null"
            ],
            "description": "A summary of what was sent. Never the payload."
          }
        }
      },
      "WebhookDeliveryAttempt": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "attemptNumber": {
            "type": "integer"
          },
          "status": {
            "type": "string"
          },
          "scheduledAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "startedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "responseStatus": {
            "type": [
              "integer",
              "null"
            ]
          },
          "latencyMs": {
            "type": [
              "integer",
              "null"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ForceStateResult": {
        "type": "object",
        "description": "What happened to one forceState entry. This exists because the failure used to be silent: a selector that matched nothing produced a capture identical to a normal one, leaving no way to tell \"this element has no hover style\" from \"nothing was ever hovered\".",
        "properties": {
          "selector": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "applied": {
            "type": "boolean"
          },
          "matched": {
            "type": "integer",
            "description": "How many elements the selector matched. Present when applied."
          },
          "note": {
            "type": "string",
            "description": "Present when the selector matched more than one element."
          },
          "reason": {
            "type": "string",
            "enum": [
              "SELECTOR_NOT_MATCHED",
              "STATE_NOT_APPLIED"
            ],
            "description": "Why it was not applied. SELECTOR_NOT_MATCHED means the page has no such element."
          },
          "error": {
            "type": "string",
            "description": "Redacted browser error, when one was raised."
          }
        }
      },
      "CaptureCredits": {
        "type": "object",
        "description": "What this request cost and what is left. Present on billable JSON responses only.",
        "properties": {
          "cost": {
            "type": "integer",
            "minimum": 0,
            "description": "Credits this request consumed."
          },
          "chargedTo": {
            "type": "string",
            "description": "Which bucket paid."
          },
          "remaining": {
            "type": [
              "integer",
              "null"
            ]
          },
          "quotaRemaining": {
            "type": [
              "integer",
              "null"
            ]
          },
          "overage": {
            "type": "boolean",
            "description": "True when the paying bucket was beyond the plan's included quota and therefore metered."
          }
        }
      },
      "ScrapeMetadata": {
        "type": "object",
        "description": "The capture metadata, plus the document fields lifted out of markdownMeta so a caller reads one object rather than two. Present on both render modes with identical field names.",
        "properties": {
          "url": {
            "type": "string",
            "description": "The URL that was requested."
          },
          "statusCode": {
            "type": [
              "integer",
              "null"
            ],
            "description": "HTTP status of the final response, after redirects. Null when the browser reported none."
          },
          "httpStatus": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Alias of statusCode, kept for parity with ScreenshotMetadata."
          },
          "renderJs": {
            "type": "boolean",
            "description": "Which engine answered: true for the browser, false for the no-browser path. Read this before concluding a page is empty."
          },
          "description": {
            "type": "string"
          },
          "ogTitle": {
            "type": "string"
          },
          "ogDescription": {
            "type": "string"
          },
          "ogImage": {
            "type": "string"
          },
          "wordCount": {
            "type": "integer",
            "minimum": 0
          },
          "charCount": {
            "type": "integer",
            "minimum": 0
          },
          "estimatedTokens": {
            "type": "integer",
            "minimum": 0,
            "description": "charCount / 4, rounded up. A budgeting estimate, not a tokenizer result."
          },
          "contentQuality": {
            "$ref": "#/components/schemas/MarkdownMetadata/properties/contentQuality"
          },
          "durationMs": {
            "type": "integer",
            "minimum": 0
          },
          "truncated": {
            "type": "boolean",
            "description": "Present and true when the transfer hit its byte cap."
          },
          "advice": {
            "type": "string",
            "description": "Present when the answer looks thin and a different render mode would likely do better."
          },
          "ignoredFields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Top-level request fields this route does not have. A typo is named here rather than rejected."
          },
          "credits": {
            "$ref": "#/components/schemas/CaptureCredits"
          }
        },
        "required": [
          "url",
          "renderJs"
        ]
      },
      "ScrapeResponse": {
        "type": "object",
        "description": "A page as a document. The same capture the /screenshot route runs, projected into the shape an agent reads: Markdown and links at the top level, and no base64 image unless screenshot:true asked for one.",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "url": {
            "type": "string",
            "description": "The canonical URL of the page, falling back to the URL requested."
          },
          "title": {
            "type": "string"
          },
          "markdown": {
            "type": "string",
            "description": "Empty string when the page yielded no extractable text."
          },
          "links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExtractedLink"
            },
            "description": "Absolute, de-duplicated, tracking-parameter-stripped links, capped at 100."
          },
          "metadata": {
            "$ref": "#/components/schemas/ScrapeMetadata"
          },
          "screenshotBase64": {
            "type": "string",
            "description": "Present only when screenshot:true was sent."
          },
          "analysis": {
            "$ref": "#/components/schemas/Analysis"
          }
        },
        "required": [
          "status",
          "url",
          "title",
          "markdown",
          "links",
          "metadata"
        ]
      }
    },
    "headers": {
      "CreditsCost": {
        "description": "Credits this request cost, after the weight table and the per-request cap. A failed request whose reservation was released reports 0: nothing was charged, and the header says so rather than advertising the reservation. The remaining-budget headers are a snapshot taken at reservation time, so on a refunded failure they under-report by the refunded amount until the next request; GET /credits is authoritative and never billed.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10
        }
      },
      "CreditsRemaining": {
        "description": "Prepaid credit balance after this request. Absent when the account holds no credits.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "QuotaRemaining": {
        "description": "Included monthly captures left before metered overage begins.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "RateLimitLimit": {
        "description": "Requests per second the plan allows.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "CaptureId": {
        "description": "Saved capture UUID. Present when a synchronous binary screenshot/PDF request sets save=true; retrieve it later with GET /capture/{captureId} using an API key owned by the same account.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "CaptureExpiresAt": {
        "description": "Effective finite retained-capture expiry for a newly saved synchronous binary response. Present with X-Domscout-Capture-Id.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "XDomscoutOverage": {
        "description": "Whether THIS request was billed beyond the plan's included quota, at the metered per-capture rate. Present as \"true\" or \"false\" on every billable response, so a client cannot confuse \"not spending\" with \"header not read\". Free control-plane reads omit it.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    },
    "x-error-codes": {
      "description": "Every error code a caller can receive, with the HTTP status it accompanies. Enumerated here rather than only described in prose so a client can be coded against the vocabulary instead of string-matching messages. Codes appear in the `code` field of ErrorResponse, in a job's terminal `error.code`, and — for ACTION_BUDGET_EXCEEDED — per step inside `actionResults`. A 4xx is terminal: the same request retried is refused again. Additive: new codes are added here in the same release that introduces them, and tests/audit-remediation-2026-08-13.test.js fails if one is not.",
      "codes": {
        "ACTION_BUDGET_EXCEEDED": {
          "status": 206,
          "meaning": "Reported per step in actionResults: the request ran out of action budget and the remaining steps were skipped."
        },
        "ACTION_EXECUTION_FAILED": {
          "status": 504,
          "meaning": "The browser session failed while executing actions and the failure carried no more specific classification."
        },
        "ACTION_FAILED": {
          "status": 400,
          "meaning": "An action failed for a reason this API does not name more precisely."
        },
        "ACTION_TIMEOUT": {
          "status": 400,
          "meaning": "An action waited for a condition that did not happen within actions[].time."
        },
        "AI_INVALID_JSON": {
          "status": 502,
          "meaning": "The AI provider did not return valid JSON."
        },
        "AI_PROVIDER_ERROR": {
          "status": 502,
          "meaning": "The AI provider returned an error. Retry shortly."
        },
        "AI_PROVIDER_INVALID_RESPONSE": {
          "status": 502,
          "meaning": "The AI provider returned a response this API could not read."
        },
        "AI_PROVIDER_MISCONFIGURED": {
          "status": 503,
          "meaning": "The AI provider is not configured correctly for this deployment."
        },
        "AI_PROVIDER_TIMEOUT": {
          "status": 504,
          "meaning": "The AI provider did not respond in time."
        },
        "AI_SCHEMA_VALIDATION_FAILED": {
          "status": 502,
          "meaning": "The AI provider returned output that did not match the supplied schema."
        },
        "ALREADY_QUEUED": {
          "status": 404,
          "meaning": "A replay of this delivery is already queued."
        },
        "ASSERTION_FAILED": {
          "status": 422,
          "meaning": "An assert action did not hold."
        },
        "ASYNC_JOBS_NOT_CONFIGURED": {
          "status": 503,
          "meaning": "This deployment has no job bucket or queue configured, so asynchronous submission, batch and crawl are unavailable to every key on every plan."
        },
        "ATTEMPTS_EXHAUSTED": {
          "status": 404,
          "meaning": "The delivery has already used all of its attempts."
        },
        "BATCH_ALREADY_SEALED": {
          "status": 400,
          "meaning": "The parent batch was sealed; its item list is final."
        },
        "BATCH_ITEM_REJECTED": {
          "status": 400,
          "meaning": "A batch item could not be enqueued; the message names why."
        },
        "BATCH_NOT_ACCEPTING_ITEMS": {
          "status": 400,
          "meaning": "The parent batch has reached a terminal or cancelling state."
        },
        "BATCH_NOT_FOUND": {
          "status": 400,
          "meaning": "The parent batch no longer exists."
        },
        "BATCH_PAGE_LIMIT_REACHED": {
          "status": 400,
          "meaning": "The batch already holds the maximum number of items."
        },
        "BATCH_QUOTA_EXCEEDED": {
          "status": 200,
          "meaning": "Reported in a batch child's error.code when the account's quota was spent before it ran."
        },
        "BROWSER_EXECUTION_DENIED": {
          "status": 403,
          "meaning": "Browser capture is refused by a platform switch, not by the plan. Almost always PUBLIC_CAPTURE_ENABLED being off, reported with reason public_capture_not_enabled, for an account without the internal-capture entitlement; also returned when a durable job is picked up after the API key that submitted it was revoked. Carries no upgrade_url: upgrading the plan does not clear it. Caller-supplied JavaScript is a different refusal, FEATURE_NOT_ENABLED."
        },
        "BROWSER_ISOLATION_REQUIRED": {
          "status": 403,
          "meaning": "Renderer isolation is not proven on this deployment, so no browser starts for anyone. A platform state rather than an account one: it is not resolved by changing plan or key, and no provisioning request clears it. Carries no upgrade_url."
        },
        "CAPTURE_ARTIFACT_CORRUPT": {
          "status": 503,
          "meaning": "The saved artifact failed its integrity check."
        },
        "CAPTURE_ARTIFACT_UNAVAILABLE": {
          "status": 503,
          "meaning": "The saved artifact could not be read from storage. Retry shortly."
        },
        "CAPTURE_NOT_FOUND": {
          "status": 404,
          "meaning": "Saved capture not found or past its retention."
        },
        "CAPTURE_RETRIEVAL_NOT_CONFIGURED": {
          "status": 503,
          "meaning": "Capture retrieval is not configured for this deployment."
        },
        "CAPTURE_SELECTOR_FAILED": {
          "status": 400,
          "meaning": "The capture selector matched an element that could not be captured."
        },
        "CAPTURE_SELECTOR_NOT_FOUND": {
          "status": 400,
          "meaning": "The capture selector matched no element."
        },
        "CAPTURE_TIMEOUT": {
          "status": 504,
          "meaning": "The browser session timed out. Retry with async:true for a 52s action budget instead of 24s."
        },
        "CAPTURE_TOO_TALL": {
          "status": 400,
          "meaning": "A fullPage capture exceeds the maximum page height."
        },
        "CAPTURE_TOO_WIDE": {
          "status": 400,
          "meaning": "A captureSelector element exceeds the maximum capture width."
        },
        "COOKIE_REJECTED": {
          "status": 400,
          "meaning": "The browser refused a supplied cookie. Its name, domain or path is invalid for the target URL — validation can only check lengths and types, so Chromium applies the real rules."
        },
        "CRAWL_CONFIGURATION_NOT_FOUND": {
          "status": 400,
          "meaning": "The crawl's configuration row is missing."
        },
        "CRAWL_DEPTH_LIMIT_REACHED": {
          "status": 400,
          "meaning": "The page is beyond maxDepth."
        },
        "CRAWL_FRONTIER_SEALED": {
          "status": 400,
          "meaning": "The crawl frontier is closed; no further pages are accepted."
        },
        "CRAWL_NOT_ACCEPTING_ITEMS": {
          "status": 400,
          "meaning": "The parent crawl has reached a terminal or cancelling state."
        },
        "CRAWL_NOT_FOUND": {
          "status": 400,
          "meaning": "The parent crawl no longer exists."
        },
        "CRAWL_PAGE_LIMIT_REACHED": {
          "status": 400,
          "meaning": "The crawl already holds maxPages pages."
        },
        "CRAWL_SEED_REJECTED": {
          "status": 400,
          "meaning": "The crawl seed could not be enqueued and the reason is not one of the specific ones below."
        },
        "CRAWL_USAGE_UNAVAILABLE": {
          "status": 200,
          "meaning": "Reported in a crawl child's error.code when its page reservation could not be made."
        },
        "DELIVERY_NOT_FOUND": {
          "status": 404,
          "meaning": "No webhook delivery with this id belongs to your account."
        },
        "DUPLICATE_CANONICAL_URL": {
          "status": 400,
          "meaning": "The page canonicalises to a URL the crawl already holds."
        },
        "EMBEDDINGS_NOT_CONFIGURED": {
          "status": 503,
          "meaning": "Semantic indexing is not configured for this deployment."
        },
        "EMBEDDING_DIMENSION_MISMATCH": {
          "status": 502,
          "meaning": "The embedding provider returned vectors of an unexpected width for this deployment."
        },
        "EMBEDDING_INVALID_RESPONSE": {
          "status": 502,
          "meaning": "The embedding provider returned an incomplete response."
        },
        "ENDPOINT_DISABLED": {
          "status": 404,
          "meaning": "The delivery's endpoint is disabled; re-enable it before replaying."
        },
        "ENDPOINT_NOT_FOUND": {
          "status": 404,
          "meaning": "The delivery's endpoint no longer exists."
        },
        "ENDPOINT_NOT_SUBSCRIBED": {
          "status": 404,
          "meaning": "The endpoint is no longer subscribed to this event type."
        },
        "EXTRACTION_REQUIRED_FIELD_MISSING": {
          "status": 422,
          "meaning": "The model returned output missing a field the schema requires."
        },
        "FEATURE_NOT_ENABLED": {
          "status": 403,
          "meaning": "A global product pause, or a trusted-JavaScript account restriction."
        },
        "FEEDBACK_LIMIT_REACHED": {
          "status": 429,
          "meaning": "The account reached its 24-hour feedback report limit. Reports are accepted again the next day and are never billed."
        },
        "FETCH_DEADLINE_EXCEEDED": {
          "status": 504,
          "meaning": "The document did not finish downloading inside the synchronous response window. Retry with async:true, or fetch a smaller document."
        },
        "FRAME_NOT_FOUND": {
          "status": 404,
          "meaning": "An action named a frame that does not exist on the page."
        },
        "IDEMPOTENCY_CONFLICT": {
          "status": 409,
          "meaning": "This Idempotency-Key was already used with a different request body."
        },
        "INJECT_JS_FAILED": {
          "status": 400,
          "meaning": "The supplied injectJS threw while executing on the page."
        },
        "INTELLIGENCE_DEADLINE_EXCEEDED": {
          "status": 504,
          "meaning": "The intelligence request took too long to finish."
        },
        "INTELLIGENCE_FINALIZATION_UNCERTAIN": {
          "status": 503,
          "meaning": "The request finished but its bookkeeping could not be confirmed."
        },
        "INTERNAL_ERROR": {
          "status": 500,
          "meaning": "An unclassified server fault. Safe to retry; if it persists, contact support with the requestId."
        },
        "ITEM_ERROR": {
          "status": 200,
          "meaning": "Reported in a batch or crawl item's error.code when the failure carried no more specific code."
        },
        "JOB_ERROR": {
          "status": 200,
          "meaning": "Reported in a job's error.code when the failure carried no more specific code. The HTTP status is that of the poll, not the failure."
        },
        "JOB_NOT_FOUND": {
          "status": 404,
          "meaning": "Unknown, expired, or malformed job id."
        },
        "LEGACY_DELIVERY_NOT_REPLAYABLE": {
          "status": 404,
          "meaning": "The delivery predates signed replay and has no stored secret snapshot."
        },
        "LLM_NOT_CONFIGURED": {
          "status": 503,
          "meaning": "LLM extraction is not configured for this deployment."
        },
        "LOCATOR_AMBIGUOUS": {
          "status": 409,
          "meaning": "An action target matched more than one element."
        },
        "LOCATOR_NOT_FOUND": {
          "status": 404,
          "meaning": "An action target matched no element."
        },
        "METHOD_NOT_ALLOWED": {
          "status": 405,
          "meaning": "The route exists but does not accept this HTTP method."
        },
        "MISSING_TARGET": {
          "status": 400,
          "meaning": "An action that requires an element target was given none."
        },
        "MONITOR_INTERVAL_TOO_SHORT": {
          "status": 400,
          "meaning": "intervalMinutes is below the minimum this plan allows."
        },
        "MONITOR_NOT_FOUND": {
          "status": 404,
          "meaning": "No monitor with this id belongs to your account. A foreign id and a missing one answer identically."
        },
        "MONITOR_PAUSED": {
          "status": 409,
          "meaning": "An on-demand run was requested for a paused monitor. Resume it first."
        },
        "MONITOR_QUOTA_EXCEEDED": {
          "status": 403,
          "meaning": "The plan's active-monitor ceiling is already reached. Pause or delete one, or upgrade."
        },
        "MONITOR_RUN_IN_FLIGHT": {
          "status": 409,
          "meaning": "A run for this monitor is already pending or running; only one is allowed at a time."
        },
        "MONITOR_UNKNOWN_FIELD": {
          "status": 400,
          "meaning": "A monitor body carried a field this API does not understand. Monitors refuse unknown fields rather than ignoring them, because a monitor runs unattended and a dropped field is wrong on every future run."
        },
        "NAVIGATION_TIMEOUT": {
          "status": 504,
          "meaning": "The target did not finish loading in time."
        },
        "NO_ACTIVE_API_KEY": {
          "status": 403,
          "meaning": "The account is authenticated but holds no active API key, so there is no credential to bill the request against. Returned only on the dashboard playground's server-to-server path; create a key, or rotate if the previous one was revoked."
        },
        "NOT_FOUND": {
          "status": 404,
          "meaning": "The addressed record does not exist or does not belong to your account."
        },
        "NOT_OWNED": {
          "status": 404,
          "meaning": "The delivery belongs to another account."
        },
        "OVERAGE_CEILING_REACHED": {
          "status": 429,
          "meaning": "The metered-overage ceiling was reached. Contact support."
        },
        "PARTIAL_FRAMES_TOO_LARGE": {
          "status": 413,
          "meaning": "Timeline frames captured before an action failure exceed the synchronous response ceiling. Retry with async:true."
        },
        "PDF_FORMAT_UNSUPPORTED": {
          "status": 400,
          "meaning": "pdfFormat is not one of the accepted paper sizes."
        },
        "PLAN_FEATURE_UNAVAILABLE": {
          "status": 403,
          "meaning": "The plan does not include this feature."
        },
        "QUOTA_EXCEEDED": {
          "status": 429,
          "meaning": "The calendar-month quota is spent. Add credits or wait for the reset."
        },
        "RATE_LIMIT_EXCEEDED": {
          "status": 429,
          "meaning": "Per-second rate limit. Retry after Retry-After."
        },
        "RENDERER_FAILED": {
          "status": 500,
          "meaning": "The renderer failed for a reason it did not classify. Report the requestId."
        },
        "RENDERER_INVALID_RESPONSE": {
          "status": 502,
          "meaning": "The capture renderer returned a payload this API could not read. Retry shortly."
        },
        "RENDERER_RESULT_TOO_LARGE": {
          "status": 413,
          "meaning": "The rendered result exceeds the transfer limit. Retry with async:true."
        },
        "RENDER_DEADLINE_EXCEEDED": {
          "status": 504,
          "meaning": "The synchronous response limit was reached. Retry with async:true."
        },
        "REQUEST_LIMIT_EXCEEDED": {
          "status": 429,
          "meaning": "A request wall was hit that this API could not classify more precisely."
        },
        "RETENTION_PERIOD_UNSUPPORTED": {
          "status": 400,
          "meaning": "retentionDays is not one of the retention periods this API offers on any plan. A period this API does offer but your plan does not is PLAN_FEATURE_UNAVAILABLE instead."
        },
        "ROBOTS_DISALLOWED": {
          "status": 403,
          "meaning": "The crawl seed is disallowed by the target robots.txt."
        },
        "SCHEMA_KEYWORD_UNSUPPORTED": {
          "status": 400,
          "meaning": "The extraction schema uses a JSON Schema keyword this API does not implement."
        },
        "SEARCH_NOT_CONFIGURED": {
          "status": 503,
          "meaning": "Web search is not configured for this deployment."
        },
        "SEARCH_PROVIDER_ERROR": {
          "status": 502,
          "meaning": "The search provider returned an error. Retry shortly."
        },
        "SEARCH_PROVIDER_MISCONFIGURED": {
          "status": 503,
          "meaning": "The search provider is not configured correctly for this deployment."
        },
        "SEARCH_PROVIDER_TIMEOUT": {
          "status": 504,
          "meaning": "The search provider did not respond in time."
        },
        "SELECT_OPTION_NOT_FOUND": {
          "status": 400,
          "meaning": "A select action named an option the target <select> does not have."
        },
        "SEMANTIC_DOCUMENT_CREATE_FAILED": {
          "status": 502,
          "meaning": "The semantic document row could not be created, so nothing was indexed. Retry shortly."
        },
        "SERVICE_MISCONFIGURED": {
          "status": 500,
          "meaning": "The deployment is refusing all requests because its CORS configuration resolves to an open wildcard in production. An operator must correct ALLOWED_ORIGINS."
        },
        "SUPABASE_INVALID_RESPONSE": {
          "status": 503,
          "meaning": "A storage operation returned a non-JSON response. Retry shortly."
        },
        "SUPABASE_REQUEST_FAILED": {
          "status": 400,
          "meaning": "A storage operation was refused. The upstream detail is deliberately withheld from the response and recorded in the request log; quote the requestId to support. Accompanies whichever 4xx the storage layer reported."
        },
        "SUPABASE_TIMEOUT": {
          "status": 503,
          "meaning": "A storage operation did not answer within its deadline. The write may or may not have committed, so a retry must be idempotent."
        },
        "TAB_CLOSE_FORBIDDEN": {
          "status": 400,
          "meaning": "A closeTab action would have closed the only open tab."
        },
        "TAB_NOT_FOUND": {
          "status": 404,
          "meaning": "A tab action named a tab that does not exist."
        },
        "TARGET_FETCH_FAILED": {
          "status": 502,
          "meaning": "A direct fetch of the target failed."
        },
        "TARGET_INVALID_RESPONSE": {
          "status": 502,
          "meaning": "The target returned a response the browser could not parse."
        },
        "TARGET_NAVIGATION_FAILED": {
          "status": 502,
          "meaning": "The target could not be loaded, for another reason the browser reported."
        },
        "TARGET_TLS_FAILED": {
          "status": 502,
          "meaning": "The target TLS certificate could not be validated."
        },
        "TARGET_UNREACHABLE": {
          "status": 502,
          "meaning": "The target refused the connection, reset it, or could not be reached."
        },
        "TOO_MANY_REDIRECTS": {
          "status": 502,
          "meaning": "The target redirected too many times."
        },
        "UNSUPPORTED_CONTENT_TYPE": {
          "status": 415,
          "meaning": "renderJs:false was asked to read a payload that is not a text document. Retry with renderJs:true, which renders it in the browser."
        },
        "UNSUPPORTED_CROSS_ORIGIN_FRAME": {
          "status": 403,
          "meaning": "The requested frame is cross-origin and cannot be driven."
        },
        "UPLOAD_SOURCE_UNSUPPORTED": {
          "status": 400,
          "meaning": "An upload action supplied a file source this API does not accept."
        },
        "UPLOAD_TOO_LARGE": {
          "status": 400,
          "meaning": "An upload action supplied a file beyond the per-file limit."
        },
        "URL_BLOCKED": {
          "status": 400,
          "meaning": "The target is loopback, private, or otherwise reserved — including IPv6 literals and cloud metadata addresses."
        },
        "URL_INVALID": {
          "status": 400,
          "meaning": "The supplied target is not a URL."
        },
        "URL_SCHEME_NOT_ALLOWED": {
          "status": 400,
          "meaning": "Only http:// and https:// URLs are dialled."
        },
        "URL_UNRESOLVABLE": {
          "status": 400,
          "meaning": "No public address resolves for the host."
        },
        "VALIDATION_FAILED": {
          "status": 400,
          "meaning": "A field is missing, malformed, or outside its documented range. The message names the field and, where there is one, the limit."
        },
        "WAIT_FOR_SELECTOR_TIMEOUT": {
          "status": 400,
          "meaning": "The top-level waitForSelector never matched a visible element."
        },
        "WEBHOOK_REPLAY_NOT_FOUND": {
          "status": 404,
          "meaning": "The delivery cannot be replayed and the reason is not one of the specific ones below."
        },
        "WORKER_ATTEMPTS_EXHAUSTED": {
          "status": 200,
          "meaning": "Reported in a job's error.code when retryable worker execution exhausted all automatic receives. The HTTP status is that of the poll, not the failure."
        },
        "WORKER_ERROR": {
          "status": 200,
          "meaning": "Reported in a job's error.code when the worker failed without classifying the cause."
        },
        "WORKFLOW_ALREADY_ACTIVE": {
          "status": 409,
          "meaning": "This API key already has an active batch or crawl. Only one parent workflow runs per key at a time; the blocking job id is returned as existingJobId."
        }
      }
    }
  }
}
