{
  "openapi": "3.1.0",
  "info": {
    "title": "String Web Access API",
    "version": "1.0.0",
    "description": "Fetch, search, and map the public web through String. Requests egress through rotating proxies with anti-bot handling, so pages that refuse ordinary automated traffic still return content. Full documentation: https://portal.usestring.ai/docs",
    "contact": {
      "name": "String",
      "url": "https://usestring.ai"
    }
  },
  "servers": [
    {
      "url": "https://request.usestring.ai/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "fetch",
      "description": "Retrieve a single URL."
    },
    {
      "name": "search",
      "description": "Query a search engine for organic results."
    },
    {
      "name": "sitemap",
      "description": "Discover the URLs of a whole site as an asynchronous job."
    },
    {
      "name": "contexts",
      "description": "Browser profiles that persist logins and cookies between sessions."
    },
    {
      "name": "sessions",
      "description": "Hosted-browser (`/wss`) sessions as API objects: ids, status, replays, live view and files. Every `/wss` connection gets an id, returned in its `x-session-id` upgrade response header."
    }
  ],
  "paths": {
    "/fetch": {
      "post": {
        "tags": [
          "fetch"
        ],
        "operationId": "fetch",
        "summary": "Fetch a URL",
        "description": "Retrieves one URL and returns it as a JSON envelope, raw bytes, or Markdown. Supply `actions` or `screenshot` to drive a real browser session before the page is captured.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FetchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The destination's response. `data` carries the page in the requested format.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FetchResponse"
                }
              }
            }
          },
          "400": {
            "description": "The request failed validation, and `issues` names the offending fields. Or `error` is `unsupported_geography`: requests cannot be routed from the requested `countryCode`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "The destination could not be reached or returned an unusable response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "`error` is `geography_unavailable`: no exit in the requested `countryCode` was available for this request. Retry it, or omit `countryCode`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/search": {
      "post": {
        "tags": [
          "search"
        ],
        "operationId": "search",
        "summary": "Search the web",
        "description": "Returns the ranked organic results, plus the local pack (`places`) and knowledge panel (`entity`) when the results page carried them. Neither is merged into `results`, so a caller counting documents is never moved by a card it cannot tell from one. `engine: \"google_ai_mode\"` answers from Google AI Mode instead: `aiMode` carries the generated answer, its structure, the pages it cites and any products, places and videos it shows; `results` is empty, and `searchCount` is rejected. `aiOverview: true` (google only, off by default) makes a second, sequential fetch to fill the AI Overview Google streams in after the page: about 64% of results pages carry one, and filling it adds about 2.8 s at p50 and 5.6 s at p90. Such a request costs 2x a normal search. An AI Overview already present in the page is returned without it.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ranked organic results and any whole-page surfaces the engine carried as JSON, or with `format: \"raw\"` the Google results page named by `page` as HTML.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The request failed validation. `issues` names the offending fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "The destination could not be reached or returned an unusable response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap": {
      "post": {
        "tags": [
          "sitemap"
        ],
        "operationId": "createSitemapJob",
        "summary": "Start a site crawl",
        "description": "Queues a crawl bounded by `maxPages` and `maxDepth`. The job is quoted and parked at `awaiting_approval`; it spends nothing until `POST /sitemap/{jobId}/approve`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SitemapRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The quoted job, awaiting approval.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitemapJobQuote"
                }
              }
            }
          },
          "400": {
            "description": "The request failed validation. `issues` names the offending fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "403": {
            "description": "The target domain is not allowed for this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainDenied"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "sitemap"
        ],
        "operationId": "listSitemapJobs",
        "summary": "List crawl jobs",
        "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
            }
          },
          {
            "name": "userId",
            "in": "query",
            "description": "Narrows the listing to one user's jobs. A filter within the caller's organization, never a widening.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of the organization's jobs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitemapJobList"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap/{jobId}": {
      "get": {
        "tags": [
          "sitemap"
        ],
        "operationId": "getSitemapJob",
        "summary": "Read a crawl job",
        "description": "The response shape depends on the job's state; see the variants of `SitemapJobState`.",
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current job state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitemapJobState"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "404": {
            "description": "No such job in the caller's organization, or its results have expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "409": {
            "description": "The job's approval handoff is incomplete; retry the approve call.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitemapConflict"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "sitemap"
        ],
        "operationId": "cancelSitemapJob",
        "summary": "Cancel a crawl job",
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The job is now `canceled`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitemapJobAck"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "404": {
            "description": "No such job in the caller's organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "409": {
            "description": "The job is already in a terminal state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitemapConflict"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap/{jobId}/approve": {
      "post": {
        "tags": [
          "sitemap"
        ],
        "operationId": "approveSitemapJob",
        "summary": "Approve a quoted crawl",
        "description": "Releases a job that is awaiting approval so it starts spending against its quote.",
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The job was already approved; its current status is returned unchanged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitemapJobAck"
                }
              }
            }
          },
          "202": {
            "description": "Approved and now running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitemapJobAck"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "402": {
            "description": "The organization cannot cover the quote.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitemapInsufficientFunds"
                }
              }
            }
          },
          "404": {
            "description": "No such job in the caller's organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "409": {
            "description": "The approval handoff is incomplete; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitemapConflict"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "500": {
            "description": "Approval failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap/{jobId}/urls": {
      "get": {
        "tags": [
          "sitemap"
        ],
        "operationId": "getSitemapUrls",
        "summary": "Read the URLs a crawl found",
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 5000,
              "default": 1000
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of discovered URLs. `total` counts them all, not this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitemapUrlPage"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "404": {
            "description": "No such job in the caller's organization, or its results have expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      }
    },
    "/contexts": {
      "post": {
        "tags": [
          "contexts"
        ],
        "operationId": "createBrowserContext",
        "summary": "Create a browser context",
        "description": "Creates an empty profile that a later `/wss` session can attach to, so logins and cookies survive between sessions.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Retry-safe creation. Replaying a completed key returns the context it created rather than a second one.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{1,255}$"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BrowserContextCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created context, or the one a replayed Idempotency-Key already created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserContext"
                }
              }
            }
          },
          "400": {
            "description": "The request failed validation. `issues` names the offending fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "409": {
            "description": "The name is taken, or a create with this Idempotency-Key is still in flight.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "The organization's context count or storage limit is reached, or its rate limit is.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "contexts"
        ],
        "operationId": "listBrowserContexts",
        "summary": "List browser contexts",
        "description": "Credit-free: an organization whose balance ran out must still be able to see what it has.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The organization's contexts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserContextList"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      }
    },
    "/contexts/{contextId}": {
      "get": {
        "tags": [
          "contexts"
        ],
        "operationId": "getBrowserContext",
        "summary": "Read a browser context",
        "description": "Credit-free.",
        "parameters": [
          {
            "name": "contextId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The context.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserContext"
                }
              }
            }
          },
          "400": {
            "description": "`contextId` is not a context UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "404": {
            "description": "No such context in the caller's organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "contexts"
        ],
        "operationId": "deleteBrowserContext",
        "summary": "Delete a browser context",
        "description": "202 is the normal answer and 200 the exception. Accepting the deletion is immediate and irreversible — the profile is never attachable again from the moment this returns — but its stored data may take a moment to be removed, so 200 is reserved for when nothing is left. A client that wants to know when that is repeats the same call.",
        "parameters": [
          {
            "name": "contextId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted; nothing remains in storage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserContextDeleted"
                }
              }
            }
          },
          "202": {
            "description": "Accepted and irreversible; the stored objects are not gone yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserContextDeleteAccepted"
                }
              }
            }
          },
          "400": {
            "description": "`contextId` is not a context UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "404": {
            "description": "No such context in the caller's organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "409": {
            "description": "The context is attached to a running session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      }
    },
    "/sessions": {
      "post": {
        "tags": [
          "sessions"
        ],
        "operationId": "createBrowserSession",
        "summary": "Create a browser session",
        "description": "Takes the same options as the `/wss` query string and returns a session to connect at `connectUrl` within ten minutes. `record: true` stores a screencast replay.",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BrowserSessionCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The pending session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserSession"
                }
              }
            }
          },
          "400": {
            "description": "The request failed validation. `issues` names the offending fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "403": {
            "description": "Browser contexts are not enabled for this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "503": {
            "description": "Session storage is not configured on this deployment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "sessions"
        ],
        "operationId": "listBrowserSessions",
        "summary": "List browser sessions",
        "description": "Newest first. Credit-free. Lists sessions made through `POST /sessions`, recorded, or given a file; any other `/wss` session is readable by its `x-session-id` for a week.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of the organization's sessions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserSessionList"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      }
    },
    "/sessions/{sessionId}": {
      "get": {
        "tags": [
          "sessions"
        ],
        "operationId": "getBrowserSession",
        "summary": "Read a browser session",
        "description": "Status, proxy route and file list. Watch a running session live by opening a WebSocket to `/sessions/{sessionId}/live` with the same `Authorization` header.",
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ses_[0-9a-f]{32}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The session and its files.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserSessionDetail"
                }
              }
            }
          },
          "400": {
            "description": "`sessionId` is not a session id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "404": {
            "description": "No such session in the caller's organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      }
    },
    "/sessions/{sessionId}/replay": {
      "get": {
        "tags": [
          "sessions"
        ],
        "operationId": "getBrowserSessionReplay",
        "summary": "Read a session replay",
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ses_[0-9a-f]{32}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Short-lived URLs for the replay's frame chunks, in order.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserSessionReplay"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "404": {
            "description": "No such session, or it was not recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "503": {
            "description": "Session storage is not configured on this deployment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      }
    },
    "/sessions/{sessionId}/files": {
      "get": {
        "tags": [
          "sessions"
        ],
        "operationId": "listBrowserSessionFiles",
        "summary": "List a session's files",
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ses_[0-9a-f]{32}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The session's files with short-lived download URLs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserSessionFileList"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "404": {
            "description": "No such session in the caller's organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      }
    },
    "/sessions/{sessionId}/files/{name}": {
      "put": {
        "tags": [
          "sessions"
        ],
        "operationId": "putBrowserSessionFile",
        "summary": "Store a file on a session",
        "description": "Stores the request body as one of the session's files, such as a receipt, replacing any file of that name. At most 26214400 bytes and 50 files per session.",
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ses_[0-9a-f]{32}$"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "*/*": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The stored file.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrowserSessionFile"
                }
              }
            }
          },
          "400": {
            "description": "The request failed validation. `issues` names the offending fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "404": {
            "description": "No such session in the caller's organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "409": {
            "description": "The session already holds 50 files.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "413": {
            "description": "The file is too large.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "503": {
            "description": "Session storage is not configured on this deployment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "sessions"
        ],
        "operationId": "getBrowserSessionFile",
        "summary": "Download a session file",
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ses_[0-9a-f]{32}$"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirects to a short-lived download URL."
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "404": {
            "description": "No such session or file.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or plan quota exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "503": {
            "description": "Session storage is not configured on this deployment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "A String API key, sent as `Authorization: Bearer <key>`. Keys are issued in the portal."
      }
    },
    "schemas": {
      "FetchRequest": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "method": {
            "enum": [
              "GET",
              "POST",
              "PUT",
              "PATCH",
              "DELETE",
              "HEAD",
              "OPTIONS",
              "get",
              "post",
              "put",
              "patch",
              "delete",
              "head",
              "options"
            ],
            "type": "string"
          },
          "format": {
            "default": "json",
            "type": "string",
            "enum": [
              "json",
              "raw",
              "markdown"
            ]
          },
          "mainContentOnly": {
            "default": false,
            "type": "boolean"
          },
          "markdownMode": {
            "default": "full",
            "type": "string",
            "enum": [
              "readable",
              "full"
            ]
          },
          "actions": {
            "minItems": 1,
            "maxItems": 50,
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "waitForNetworkIdle"
                    },
                    "idleTime": {
                      "description": "Milliseconds the network must stay quiet, at most 10000. Defaults to 500.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 10000
                    },
                    "concurrency": {
                      "description": "Requests that may stay in flight while the network counts as quiet, at most 10. Defaults to 0; 1 or 2 suits a page that holds a long-poll or analytics connection open.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 10
                    },
                    "timeout": {
                      "description": "Milliseconds to wait for the network to go quiet, at most 30000 (the default).",
                      "type": "integer",
                      "exclusiveMinimum": 0,
                      "maximum": 30000
                    },
                    "onTimeout": {
                      "description": "`continue` (default): the sequence carries on with the page as it is and the action is listed in `timedOutActions`. `fail`: the sequence fails at this action.",
                      "type": "string",
                      "enum": [
                        "fail",
                        "continue"
                      ]
                    }
                  },
                  "required": [
                    "type"
                  ],
                  "additionalProperties": false,
                  "description": "Waits until the page has had no more than `concurrency` requests in flight for `idleTime` milliseconds. The defaults wait like `waitUntil: \"networkidle0\"`, and `concurrency: 2` waits like `networkidle2`."
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "wait"
                    },
                    "milliseconds": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 30000
                    },
                    "selector": {
                      "type": "string"
                    },
                    "timeout": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 30000
                    },
                    "frame": {
                      "description": "Runs the action inside an iframe, cross-origin ones included: a selector for the `<iframe>` element, such as `iframe[src*=\"checkout\"]` or `iframe[name=\"reviews\"]`, or for an iframe inside another iframe, a list of selectors from the outermost iframe in, at most 5. Each selector uses its first match, and the action's own `selector` is looked up in that iframe's document. write and press type into whatever has focus, so a click on a field inside an iframe directs them there.",
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1
                        },
                        {
                          "minItems": 1,
                          "maxItems": 5,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1
                          }
                        }
                      ]
                    }
                  },
                  "required": [
                    "type"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "click"
                    },
                    "selector": {
                      "type": "string"
                    },
                    "all": {
                      "type": "boolean"
                    },
                    "frame": {
                      "description": "Runs the action inside an iframe, cross-origin ones included: a selector for the `<iframe>` element, such as `iframe[src*=\"checkout\"]` or `iframe[name=\"reviews\"]`, or for an iframe inside another iframe, a list of selectors from the outermost iframe in, at most 5. Each selector uses its first match, and the action's own `selector` is looked up in that iframe's document. write and press type into whatever has focus, so a click on a field inside an iframe directs them there.",
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1
                        },
                        {
                          "minItems": 1,
                          "maxItems": 5,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1
                          }
                        }
                      ]
                    }
                  },
                  "required": [
                    "type",
                    "selector"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "write"
                    },
                    "text": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "text"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "press"
                    },
                    "key": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "key"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "scroll"
                    },
                    "direction": {
                      "type": "string",
                      "enum": [
                        "up",
                        "down",
                        "left",
                        "right"
                      ]
                    },
                    "amount": {
                      "type": "integer",
                      "exclusiveMinimum": 0,
                      "maximum": 9007199254740991
                    },
                    "selector": {
                      "type": "string"
                    },
                    "frame": {
                      "description": "Runs the action inside an iframe, cross-origin ones included: a selector for the `<iframe>` element, such as `iframe[src*=\"checkout\"]` or `iframe[name=\"reviews\"]`, or for an iframe inside another iframe, a list of selectors from the outermost iframe in, at most 5. Each selector uses its first match, and the action's own `selector` is looked up in that iframe's document. write and press type into whatever has focus, so a click on a field inside an iframe directs them there. Without `selector`, scrolls the iframe's own document by `direction` and `amount`.",
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1
                        },
                        {
                          "minItems": 1,
                          "maxItems": 5,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1
                          }
                        }
                      ]
                    }
                  },
                  "required": [
                    "type"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "screenshot"
                    },
                    "full_page": {
                      "type": "boolean"
                    },
                    "quality": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 100
                    }
                  },
                  "required": [
                    "type"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "navigate"
                    },
                    "url": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "url"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "hover"
                    },
                    "selector": {
                      "type": "string"
                    },
                    "frame": {
                      "description": "Runs the action inside an iframe, cross-origin ones included: a selector for the `<iframe>` element, such as `iframe[src*=\"checkout\"]` or `iframe[name=\"reviews\"]`, or for an iframe inside another iframe, a list of selectors from the outermost iframe in, at most 5. Each selector uses its first match, and the action's own `selector` is looked up in that iframe's document. write and press type into whatever has focus, so a click on a field inside an iframe directs them there.",
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1
                        },
                        {
                          "minItems": 1,
                          "maxItems": 5,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1
                          }
                        }
                      ]
                    }
                  },
                  "required": [
                    "type",
                    "selector"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "selectOption"
                    },
                    "selector": {
                      "type": "string"
                    },
                    "value": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      ]
                    },
                    "frame": {
                      "description": "Runs the action inside an iframe, cross-origin ones included: a selector for the `<iframe>` element, such as `iframe[src*=\"checkout\"]` or `iframe[name=\"reviews\"]`, or for an iframe inside another iframe, a list of selectors from the outermost iframe in, at most 5. Each selector uses its first match, and the action's own `selector` is looked up in that iframe's document. write and press type into whatever has focus, so a click on a field inside an iframe directs them there.",
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1
                        },
                        {
                          "minItems": 1,
                          "maxItems": 5,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1
                          }
                        }
                      ]
                    }
                  },
                  "required": [
                    "type",
                    "selector",
                    "value"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "waitForResponse"
                    },
                    "url": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 2048,
                      "description": "The pattern matched against the full request URL, query string included. How it matches is set by `match`."
                    },
                    "match": {
                      "default": "contains",
                      "description": "`contains`: the URL contains `url`, case-sensitive. `glob`: `url` matches the whole URL, case-sensitive, where `*` matches any run of characters including `/`, `?` matches exactly one character, and every other character matches itself. `regex`: `url` is an RE2 regular expression (https://github.com/google/re2/wiki/Syntax) that matches anywhere in the URL; anchor it with `^` and `$` to match the whole URL.",
                      "type": "string",
                      "enum": [
                        "contains",
                        "glob",
                        "regex"
                      ]
                    },
                    "methods": {
                      "description": "Matches only requests sent with one of these methods, in any case.",
                      "minItems": 1,
                      "maxItems": 7,
                      "type": "array",
                      "items": {
                        "enum": [
                          "GET",
                          "POST",
                          "PUT",
                          "PATCH",
                          "DELETE",
                          "HEAD",
                          "OPTIONS",
                          "get",
                          "post",
                          "put",
                          "patch",
                          "delete",
                          "head",
                          "options"
                        ],
                        "type": "string"
                      }
                    },
                    "statusCodes": {
                      "description": "Matches only requests whose response has one of these status codes. A request that failed or had no response yet never matches.",
                      "minItems": 1,
                      "maxItems": 20,
                      "type": "array",
                      "items": {
                        "type": "integer",
                        "minimum": 100,
                        "maximum": 599
                      }
                    },
                    "timeout": {
                      "description": "Milliseconds to wait for a matching response, at most 30000 (the default).",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 30000
                    },
                    "onTimeout": {
                      "description": "`fail` (default): no matching response within `timeout` fails the sequence at this action. `continue`: the sequence carries on with the next action.",
                      "type": "string",
                      "enum": [
                        "fail",
                        "continue"
                      ]
                    },
                    "asResult": {
                      "description": "Return the matched response instead of the page: `data` carries its body and `matchedResponse` its URL, method, status code, headers and body encoding, while `statusCode`, `headers` and `finalUrl` stay the page's. Applies only when the sequence succeeds and this action matched a response. The body is limited to 10 MiB; a larger or unreadable body, or a response that cannot be returned, fails this action. At most one action may set it, and it requires format \"json\" and no jsonSchema.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "type",
                    "url"
                  ],
                  "additionalProperties": false,
                  "description": "Waits for an XHR or fetch() response that matches `url`, `match`, `methods` and `statusCodes` (the same conditions as a captureXHR filter) and has finished loading. A matching response that finished after the last action before it that can start traffic started counts, so one the preceding click, press or scroll triggered is not missed, even with a wait for a selector in between; at the start of the sequence, responses from the page load count. The waitForResponse actions after one such action share that window and each takes a different response, so two waits after one click can match two responses the click triggered. The earliest matching response wins."
                }
              ]
            }
          },
          "screenshot": {
            "type": "boolean"
          },
          "includeIframes": {
            "description": "Inline the content of every iframe on the final page into `data`, cross-origin iframes included. Each iframe's document follows its `<iframe>` element as `<div data-iframe-id=\"…\" data-iframe-url=\"…\">` (with `data-iframe-name` when the iframe has a name), holding the content of its head and body with relative URLs made absolute; an iframe's own iframes are inlined inside it the same way. `data-iframe-id` is the `id` the same iframe has in `iframes` with captureIframes. Applies to every format and to jsonSchema extraction. Requires executeJS: true, actions or screenshot. Up to 50 iframes, 5 levels deep and 4 MiB of HTML, counting the page itself, so a page over 4 MiB on its own comes back without its iframes. When a limit, or an iframe that cannot be read in time, leaves content out, `iframesTruncated` is true.",
            "type": "boolean"
          },
          "captureIframes": {
            "description": "Return the final page's iframes, cross-origin ones included, as `iframes` in the JSON envelope. `true` or `{}` returns every iframe's HTML; `{ \"include\": [...] }` returns the HTML of only the iframes whose URL matches a filter. A captured `xhr` request's `frameId` names the iframe that sent it. Requires executeJS: true, actions or screenshot, and format: \"json\" unless the request uses actions or screenshot. Up to 50 iframes, 5 levels deep, 2 MiB of HTML per iframe and 4 MiB in total; `iframesTruncated` is true when a limit left an iframe or its HTML out.",
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "object",
                "properties": {
                  "include": {
                    "description": "Carries the HTML of only the iframes whose URL matches at least one of these filters; every iframe is still listed. Each matching iframe carries `matchedFilter`, the index of the first filter it matched.",
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 2048,
                          "description": "The pattern matched against the full URL of the iframe's document, query string included. How it matches is set by `match`."
                        },
                        "match": {
                          "default": "contains",
                          "description": "`contains`: the URL contains `url`, case-sensitive. `glob`: `url` matches the whole URL, case-sensitive, where `*` matches any run of characters including `/`, `?` matches exactly one character, and every other character matches itself. `regex`: `url` is an RE2 regular expression (https://github.com/google/re2/wiki/Syntax) that matches anywhere in the URL; anchor it with `^` and `$` to match the whole URL.",
                          "type": "string",
                          "enum": [
                            "contains",
                            "glob",
                            "regex"
                          ]
                        }
                      },
                      "required": [
                        "url"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "additionalProperties": false
              }
            ]
          },
          "requireWSS": {
            "type": "boolean"
          },
          "executeJS": {
            "type": "boolean"
          },
          "waitUntil": {
            "description": "Waits for the page to reach this state before it is read: `domcontentloaded` (the HTML is parsed), `load` (the load event, after images, frames and stylesheets), `networkidle0` (no request in flight for 500 ms; `networkidle` is the same) or `networkidle2` (at most 2 requests in flight for 500 ms). With actions or screenshot it applies to opening `url`, in place of the usual settle before the first action. The wait gives up after 10 seconds, leaves the page as it is, and the response carries `waitUntilTimedOut: true`. Requires executeJS: true, actions or screenshot.",
            "type": "string",
            "enum": [
              "domcontentloaded",
              "load",
              "networkidle0",
              "networkidle2",
              "networkidle"
            ]
          },
          "captureXHR": {
            "description": "Return the XHR and fetch() requests the page makes, with their responses, as `xhr` in the JSON envelope. Requests from iframes on the same site as the page are included; requests from cross-site iframes are included only with `{ \"iframes\": true }`. `true` or `{}` returns every request; `{ \"include\": [...] }` returns only the requests that match a filter. Requires executeJS: true, and format: \"json\" unless the request uses actions or screenshot, in which case requests from the whole session are included. Up to 200 requests and 10 MiB in total, iframe requests included, and response bodies over 2 MiB are omitted; when a limit leaves anything out, `xhrTruncated` is true. Requests your access policy denies are blocked. Returns HTTP 503 when capture is temporarily unavailable.",
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "object",
                "properties": {
                  "include": {
                    "description": "Returns only the requests that match at least one of these filters; a request matches a filter when it meets every condition the filter sets. A request that matches none is left out before any limit applies, so it takes none of the 200 requests or 10 MiB and does not set `xhrTruncated`. Each returned request carries `matchedFilter`, the index of the first filter it matched.",
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 2048,
                          "description": "The pattern matched against the full request URL, query string included. How it matches is set by `match`."
                        },
                        "match": {
                          "default": "contains",
                          "description": "`contains`: the URL contains `url`, case-sensitive. `glob`: `url` matches the whole URL, case-sensitive, where `*` matches any run of characters including `/`, `?` matches exactly one character, and every other character matches itself. `regex`: `url` is an RE2 regular expression (https://github.com/google/re2/wiki/Syntax) that matches anywhere in the URL; anchor it with `^` and `$` to match the whole URL.",
                          "type": "string",
                          "enum": [
                            "contains",
                            "glob",
                            "regex"
                          ]
                        },
                        "methods": {
                          "description": "Matches only requests sent with one of these methods, in any case.",
                          "minItems": 1,
                          "maxItems": 7,
                          "type": "array",
                          "items": {
                            "enum": [
                              "GET",
                              "POST",
                              "PUT",
                              "PATCH",
                              "DELETE",
                              "HEAD",
                              "OPTIONS",
                              "get",
                              "post",
                              "put",
                              "patch",
                              "delete",
                              "head",
                              "options"
                            ],
                            "type": "string"
                          }
                        },
                        "statusCodes": {
                          "description": "Matches only requests whose response has one of these status codes. A request that failed or had no response yet never matches.",
                          "minItems": 1,
                          "maxItems": 20,
                          "type": "array",
                          "items": {
                            "type": "integer",
                            "minimum": 100,
                            "maximum": 599
                          }
                        }
                      },
                      "required": [
                        "url"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "iframes": {
                    "description": "Also return the requests made by cross-site iframes, such as payment, map, chat or review widgets. Cross-site iframes are followed two levels deep, and up to 32 cross-site iframes at a time; one past those limits is not followed and sets `xhrTruncated`. Iframe requests count toward the page's 200-request and 10 MiB limits.",
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            ]
          },
          "captureCookies": {
            "description": "Return the cookies the browser would send to the final page URL once the page has loaded, as `cookies` in the JSON envelope, HttpOnly cookies included. Each has `name` and `value`, plus `domain`, `path`, `expires`, `httpOnly` and `secure` when the browser reports them. Requires executeJS: true, actions or screenshot, and format: \"json\" unless the request runs actions or screenshot; cannot be combined with jsonSchema. With actions, the cookies are read once the last action has run. When the cookies could not be read for this response, `cookies` is empty and `cookiesTruncated` is true.",
            "type": "boolean"
          },
          "headers": {
            "type": "object",
            "propertyNames": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256
            },
            "additionalProperties": {
              "type": "string"
            }
          },
          "countryCode": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2
          },
          "solveCaptcha": {
            "default": true,
            "type": "boolean"
          },
          "ignoreCertificateErrors": {
            "default": true,
            "type": "boolean"
          },
          "followRedirects": {
            "description": "Send false to return the destination's redirect response itself instead of following it, the same as maxRedirects: 0. The `x-redirect-url` response header then holds the absolute URL it pointed to. Defaults to true. Cannot be combined with maxRedirects, executeJS, requireWSS, captureXHR, actions or screenshot. The page is never rendered in a browser.",
            "type": "boolean"
          },
          "maxRedirects": {
            "description": "The most redirects to follow, up to 10. When the destination redirects again after that, its redirect response is returned and billed, with the URL it pointed to on the `x-redirect-url` response header. Cannot be combined with followRedirects: false, executeJS, requireWSS, captureXHR, actions or screenshot. The page is never rendered in a browser.",
            "type": "integer",
            "minimum": 0,
            "maximum": 10
          },
          "jsonSchema": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {}
          },
          "body": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "properties": {},
                "additionalProperties": {}
              }
            ],
            "description": "Request body. A string is forwarded as its exact bytes. An object is forwarded as the JSON text the caller sent for it, byte for byte."
          }
        },
        "required": [
          "url"
        ],
        "additionalProperties": false
      },
      "FetchResponse": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "statusCode": {
                "type": "number"
              },
              "headers": {
                "type": "object",
                "propertyNames": {
                  "type": "string"
                },
                "additionalProperties": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  ]
                }
              },
              "data": {},
              "pdf": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "extracted",
                      "no_text",
                      "failed"
                    ],
                    "description": "`extracted`: `text` holds the document's text. `no_text`: the PDF parsed but has no text layer (a scan), so `text` is empty and `pagesNeedingOcr` lists every page. `failed`: see `reason`."
                  },
                  "reason": {
                    "description": "Why a `failed` extraction failed: `too_large` (over 32 MiB), `timeout` (over 20 seconds), `encrypted`, `unparseable`, `aborted` (the client disconnected), or `unavailable` (text extraction could not be reached; try again later).",
                    "type": "string",
                    "enum": [
                      "too_large",
                      "timeout",
                      "encrypted",
                      "unparseable",
                      "aborted",
                      "unavailable"
                    ]
                  },
                  "text": {
                    "type": "string",
                    "description": "The text, page by page, each page after a `<!-- Page N -->` marker. Empty unless `extracted`."
                  },
                  "pageCount": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  },
                  "pagesNeedingOcr": {
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "exclusiveMinimum": 0,
                      "maximum": 9007199254740991
                    },
                    "description": "1-indexed pages whose text layer is missing or unreliable."
                  },
                  "truncated": {
                    "description": "True when `text` stopped at a page boundary at 2 MiB.",
                    "type": "boolean"
                  },
                  "durationMs": {
                    "type": "number",
                    "minimum": 0
                  }
                },
                "required": [
                  "status",
                  "text",
                  "pageCount",
                  "pagesNeedingOcr",
                  "durationMs"
                ],
                "additionalProperties": false,
                "description": "Present when the response is a PDF: its extracted text. `data` still carries the original bytes as a base64 data URI."
              },
              "iframes": {
                "description": "Present when the request set captureIframes: the final page's iframes, each before the iframes nested in it. Empty when the page had none.",
                "maxItems": 50,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "maxLength": 128,
                      "description": "An opaque id for the iframe. A captured `xhr` request's `frameId`, and with includeIframes the `data-iframe-id` of the iframe's inlined content, name the same iframe."
                    },
                    "parentId": {
                      "description": "The `id` of the iframe this one is nested in; absent for an iframe of the page itself.",
                      "type": "string",
                      "maxLength": 128
                    },
                    "depth": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 9007199254740991,
                      "description": "1 for an iframe of the page itself, 2 for one nested inside it, and so on."
                    },
                    "url": {
                      "type": "string",
                      "maxLength": 8192,
                      "description": "The URL of the iframe's document when the page was read."
                    },
                    "src": {
                      "description": "The `<iframe>` element's `src` attribute, as written in its parent.",
                      "type": "string",
                      "maxLength": 8192
                    },
                    "name": {
                      "description": "The `<iframe>` element's `name` attribute.",
                      "type": "string",
                      "maxLength": 1024
                    },
                    "selector": {
                      "description": "A selector for the `<iframe>` element in its parent's document. The selectors from the outermost iframe in, as a list, make an action's `frame` for this iframe.",
                      "type": "string",
                      "maxLength": 4096
                    },
                    "crossOrigin": {
                      "type": "boolean",
                      "description": "Whether the iframe's document is from another origin than the page."
                    },
                    "statusCode": {
                      "description": "The HTTP status of the iframe's document, when the browser loaded it over HTTP.",
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "html": {
                      "description": "The iframe's document, serialized from the live DOM when the page was read.",
                      "type": "string"
                    },
                    "htmlOmitted": {
                      "description": "Why `html` is absent: `not_matched` (no `include` filter matched the iframe's URL), `too_large` (over 2 MiB), `budget_exhausted` (the HTML read reached its 4 MiB limit), or `unavailable` (the iframe could not be read in time).",
                      "type": "string",
                      "enum": [
                        "not_matched",
                        "too_large",
                        "budget_exhausted",
                        "unavailable"
                      ]
                    },
                    "matchedFilter": {
                      "description": "Present when captureIframes set `include`: the 0-based index of the first filter the iframe's URL matched.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "id",
                    "depth",
                    "url",
                    "crossOrigin"
                  ],
                  "additionalProperties": false
                }
              },
              "iframesTruncated": {
                "description": "True when includeIframes or captureIframes left an iframe or its content out. Also sent as the `x-iframes-truncated: true` header, which a markdown, raw or jsonSchema response carries too.",
                "type": "boolean"
              },
              "finalUrl": {
                "type": "string"
              },
              "waitUntilTimedOut": {
                "description": "True when the page was read before it reached the request's `waitUntil` state, because the wait ran out.",
                "type": "boolean"
              },
              "xhr": {
                "description": "Present when the request set captureXHR: the XHR and fetch() requests the page made, in the order it made them, across the whole session for a request with actions. Up to 200 requests and 10 MiB in total, iframe requests included. A request with neither `response` nor `error` had not completed when the page was read. Empty when no requests were captured.",
                "maxItems": 200,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "resourceType": {
                      "type": "string",
                      "enum": [
                        "xhr",
                        "fetch"
                      ]
                    },
                    "frameUrl": {
                      "description": "The URL of the document that sent the request: the page's own, or that of the iframe the request came from. Absent when it is not known.",
                      "type": "string"
                    },
                    "frameId": {
                      "description": "An id for the frame that sent the request, absent when it is not known. With captureIframes, the iframe's entry in `iframes` has the same `id`.",
                      "type": "string",
                      "maxLength": 128
                    },
                    "request": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "type": "string"
                        },
                        "method": {
                          "type": "string"
                        },
                        "headers": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {
                            "type": "string"
                          }
                        },
                        "body": {
                          "description": "The request body as the page sent it, encoded as declared by bodyEncoding.",
                          "type": "string",
                          "maxLength": 2796204
                        },
                        "bodyEncoding": {
                          "description": "`utf8` for text, `base64` for binary content.",
                          "type": "string",
                          "enum": [
                            "utf8",
                            "base64"
                          ]
                        },
                        "bodyOmitted": {
                          "description": "Why `body` is absent: `too_large` (the body is too large to include), `budget_exhausted` (the `xhr` list reached its 10 MiB limit), or `unavailable` (the body could not be captured).",
                          "type": "string",
                          "enum": [
                            "too_large",
                            "budget_exhausted",
                            "unavailable"
                          ]
                        }
                      },
                      "required": [
                        "url",
                        "method",
                        "headers"
                      ],
                      "additionalProperties": false
                    },
                    "response": {
                      "description": "Absent when no response arrived.",
                      "type": "object",
                      "properties": {
                        "statusCode": {
                          "type": "number"
                        },
                        "headers": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {
                            "type": "string"
                          }
                        },
                        "body": {
                          "type": "string",
                          "maxLength": 2796204
                        },
                        "bodyEncoding": {
                          "description": "`utf8` for text, `base64` for binary content.",
                          "type": "string",
                          "enum": [
                            "utf8",
                            "base64"
                          ]
                        },
                        "bodyOmitted": {
                          "description": "Why `body` is absent: `too_large` (over 2 MiB), `budget_exhausted` (the `xhr` list reached its 10 MiB limit), or `unavailable` (the body could not be captured, for example for a redirect or an aborted request).",
                          "type": "string",
                          "enum": [
                            "too_large",
                            "budget_exhausted",
                            "unavailable"
                          ]
                        }
                      },
                      "required": [
                        "statusCode",
                        "headers"
                      ],
                      "additionalProperties": false
                    },
                    "error": {
                      "description": "The network error, when the request failed.",
                      "type": "string"
                    },
                    "matchedFilter": {
                      "description": "Present when captureXHR set `include`: the 0-based index of the first filter in `include` this request matched.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "timing": {
                      "description": "When the request was sent and how long it took.",
                      "type": "object",
                      "properties": {
                        "startedAt": {
                          "type": "number",
                          "minimum": 0,
                          "description": "When the page sent the request, in milliseconds since the Unix epoch."
                        },
                        "durationMs": {
                          "description": "Milliseconds from sending the request until its response finished loading or it failed. Absent while it was still in flight.",
                          "type": "number",
                          "minimum": 0
                        }
                      },
                      "required": [
                        "startedAt"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "resourceType",
                    "request"
                  ],
                  "additionalProperties": false
                }
              },
              "xhrTruncated": {
                "description": "True when a capture limit left requests or bodies out of `xhr`, or when the page's requests could not be captured for this response.",
                "type": "boolean"
              },
              "cookies": {
                "description": "With captureCookies: the cookies the browser would send to the final page URL once it loaded, empty when they could not be read.",
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "value": {
                      "type": "string"
                    },
                    "domain": {
                      "type": "string"
                    },
                    "path": {
                      "type": "string"
                    },
                    "expires": {
                      "description": "Expiry as Unix time in seconds; -1 for a session cookie.",
                      "type": "number"
                    },
                    "httpOnly": {
                      "type": "boolean"
                    },
                    "secure": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "name",
                    "value"
                  ],
                  "additionalProperties": false
                }
              },
              "cookiesTruncated": {
                "description": "True when captureCookies was set and the cookies could not be read for this response, so `cookies` is empty.",
                "type": "boolean"
              },
              "extracted": {
                "type": "boolean",
                "const": false
              },
              "reason": {
                "type": "string",
                "enum": [
                  "empty_body",
                  "body_too_large",
                  "llm_error",
                  "unparseable_output",
                  "schema_mismatch"
                ]
              }
            },
            "required": [
              "statusCode",
              "headers",
              "data",
              "finalUrl",
              "extracted",
              "reason"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "statusCode": {
                "type": "number"
              },
              "headers": {
                "type": "object",
                "propertyNames": {
                  "type": "string"
                },
                "additionalProperties": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  ]
                }
              },
              "data": {},
              "pdf": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "extracted",
                      "no_text",
                      "failed"
                    ],
                    "description": "`extracted`: `text` holds the document's text. `no_text`: the PDF parsed but has no text layer (a scan), so `text` is empty and `pagesNeedingOcr` lists every page. `failed`: see `reason`."
                  },
                  "reason": {
                    "description": "Why a `failed` extraction failed: `too_large` (over 32 MiB), `timeout` (over 20 seconds), `encrypted`, `unparseable`, `aborted` (the client disconnected), or `unavailable` (text extraction could not be reached; try again later).",
                    "type": "string",
                    "enum": [
                      "too_large",
                      "timeout",
                      "encrypted",
                      "unparseable",
                      "aborted",
                      "unavailable"
                    ]
                  },
                  "text": {
                    "type": "string",
                    "description": "The text, page by page, each page after a `<!-- Page N -->` marker. Empty unless `extracted`."
                  },
                  "pageCount": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  },
                  "pagesNeedingOcr": {
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "exclusiveMinimum": 0,
                      "maximum": 9007199254740991
                    },
                    "description": "1-indexed pages whose text layer is missing or unreliable."
                  },
                  "truncated": {
                    "description": "True when `text` stopped at a page boundary at 2 MiB.",
                    "type": "boolean"
                  },
                  "durationMs": {
                    "type": "number",
                    "minimum": 0
                  }
                },
                "required": [
                  "status",
                  "text",
                  "pageCount",
                  "pagesNeedingOcr",
                  "durationMs"
                ],
                "additionalProperties": false,
                "description": "Present when the response is a PDF: its extracted text. `data` still carries the original bytes as a base64 data URI."
              },
              "iframes": {
                "description": "Present when the request set captureIframes: the final page's iframes, each before the iframes nested in it. Empty when the page had none.",
                "maxItems": 50,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "maxLength": 128,
                      "description": "An opaque id for the iframe. A captured `xhr` request's `frameId`, and with includeIframes the `data-iframe-id` of the iframe's inlined content, name the same iframe."
                    },
                    "parentId": {
                      "description": "The `id` of the iframe this one is nested in; absent for an iframe of the page itself.",
                      "type": "string",
                      "maxLength": 128
                    },
                    "depth": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 9007199254740991,
                      "description": "1 for an iframe of the page itself, 2 for one nested inside it, and so on."
                    },
                    "url": {
                      "type": "string",
                      "maxLength": 8192,
                      "description": "The URL of the iframe's document when the page was read."
                    },
                    "src": {
                      "description": "The `<iframe>` element's `src` attribute, as written in its parent.",
                      "type": "string",
                      "maxLength": 8192
                    },
                    "name": {
                      "description": "The `<iframe>` element's `name` attribute.",
                      "type": "string",
                      "maxLength": 1024
                    },
                    "selector": {
                      "description": "A selector for the `<iframe>` element in its parent's document. The selectors from the outermost iframe in, as a list, make an action's `frame` for this iframe.",
                      "type": "string",
                      "maxLength": 4096
                    },
                    "crossOrigin": {
                      "type": "boolean",
                      "description": "Whether the iframe's document is from another origin than the page."
                    },
                    "statusCode": {
                      "description": "The HTTP status of the iframe's document, when the browser loaded it over HTTP.",
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "html": {
                      "description": "The iframe's document, serialized from the live DOM when the page was read.",
                      "type": "string"
                    },
                    "htmlOmitted": {
                      "description": "Why `html` is absent: `not_matched` (no `include` filter matched the iframe's URL), `too_large` (over 2 MiB), `budget_exhausted` (the HTML read reached its 4 MiB limit), or `unavailable` (the iframe could not be read in time).",
                      "type": "string",
                      "enum": [
                        "not_matched",
                        "too_large",
                        "budget_exhausted",
                        "unavailable"
                      ]
                    },
                    "matchedFilter": {
                      "description": "Present when captureIframes set `include`: the 0-based index of the first filter the iframe's URL matched.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "id",
                    "depth",
                    "url",
                    "crossOrigin"
                  ],
                  "additionalProperties": false
                }
              },
              "iframesTruncated": {
                "description": "True when includeIframes or captureIframes left an iframe or its content out. Also sent as the `x-iframes-truncated: true` header, which a markdown, raw or jsonSchema response carries too.",
                "type": "boolean"
              },
              "finalUrl": {
                "type": "string"
              },
              "waitUntilTimedOut": {
                "description": "True when the page was read before it reached the request's `waitUntil` state, because the wait ran out.",
                "type": "boolean"
              },
              "xhr": {
                "description": "Present when the request set captureXHR: the XHR and fetch() requests the page made, in the order it made them, across the whole session for a request with actions. Up to 200 requests and 10 MiB in total, iframe requests included. A request with neither `response` nor `error` had not completed when the page was read. Empty when no requests were captured.",
                "maxItems": 200,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "resourceType": {
                      "type": "string",
                      "enum": [
                        "xhr",
                        "fetch"
                      ]
                    },
                    "frameUrl": {
                      "description": "The URL of the document that sent the request: the page's own, or that of the iframe the request came from. Absent when it is not known.",
                      "type": "string"
                    },
                    "frameId": {
                      "description": "An id for the frame that sent the request, absent when it is not known. With captureIframes, the iframe's entry in `iframes` has the same `id`.",
                      "type": "string",
                      "maxLength": 128
                    },
                    "request": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "type": "string"
                        },
                        "method": {
                          "type": "string"
                        },
                        "headers": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {
                            "type": "string"
                          }
                        },
                        "body": {
                          "description": "The request body as the page sent it, encoded as declared by bodyEncoding.",
                          "type": "string",
                          "maxLength": 2796204
                        },
                        "bodyEncoding": {
                          "description": "`utf8` for text, `base64` for binary content.",
                          "type": "string",
                          "enum": [
                            "utf8",
                            "base64"
                          ]
                        },
                        "bodyOmitted": {
                          "description": "Why `body` is absent: `too_large` (the body is too large to include), `budget_exhausted` (the `xhr` list reached its 10 MiB limit), or `unavailable` (the body could not be captured).",
                          "type": "string",
                          "enum": [
                            "too_large",
                            "budget_exhausted",
                            "unavailable"
                          ]
                        }
                      },
                      "required": [
                        "url",
                        "method",
                        "headers"
                      ],
                      "additionalProperties": false
                    },
                    "response": {
                      "description": "Absent when no response arrived.",
                      "type": "object",
                      "properties": {
                        "statusCode": {
                          "type": "number"
                        },
                        "headers": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {
                            "type": "string"
                          }
                        },
                        "body": {
                          "type": "string",
                          "maxLength": 2796204
                        },
                        "bodyEncoding": {
                          "description": "`utf8` for text, `base64` for binary content.",
                          "type": "string",
                          "enum": [
                            "utf8",
                            "base64"
                          ]
                        },
                        "bodyOmitted": {
                          "description": "Why `body` is absent: `too_large` (over 2 MiB), `budget_exhausted` (the `xhr` list reached its 10 MiB limit), or `unavailable` (the body could not be captured, for example for a redirect or an aborted request).",
                          "type": "string",
                          "enum": [
                            "too_large",
                            "budget_exhausted",
                            "unavailable"
                          ]
                        }
                      },
                      "required": [
                        "statusCode",
                        "headers"
                      ],
                      "additionalProperties": false
                    },
                    "error": {
                      "description": "The network error, when the request failed.",
                      "type": "string"
                    },
                    "matchedFilter": {
                      "description": "Present when captureXHR set `include`: the 0-based index of the first filter in `include` this request matched.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "timing": {
                      "description": "When the request was sent and how long it took.",
                      "type": "object",
                      "properties": {
                        "startedAt": {
                          "type": "number",
                          "minimum": 0,
                          "description": "When the page sent the request, in milliseconds since the Unix epoch."
                        },
                        "durationMs": {
                          "description": "Milliseconds from sending the request until its response finished loading or it failed. Absent while it was still in flight.",
                          "type": "number",
                          "minimum": 0
                        }
                      },
                      "required": [
                        "startedAt"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "resourceType",
                    "request"
                  ],
                  "additionalProperties": false
                }
              },
              "xhrTruncated": {
                "description": "True when a capture limit left requests or bodies out of `xhr`, or when the page's requests could not be captured for this response.",
                "type": "boolean"
              },
              "cookies": {
                "description": "With captureCookies: the cookies the browser would send to the final page URL once it loaded, empty when they could not be read.",
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "value": {
                      "type": "string"
                    },
                    "domain": {
                      "type": "string"
                    },
                    "path": {
                      "type": "string"
                    },
                    "expires": {
                      "description": "Expiry as Unix time in seconds; -1 for a session cookie.",
                      "type": "number"
                    },
                    "httpOnly": {
                      "type": "boolean"
                    },
                    "secure": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "name",
                    "value"
                  ],
                  "additionalProperties": false
                }
              },
              "cookiesTruncated": {
                "description": "True when captureCookies was set and the cookies could not be read for this response, so `cookies` is empty.",
                "type": "boolean"
              },
              "extracted": {},
              "reason": {}
            },
            "required": [
              "statusCode",
              "headers",
              "data",
              "finalUrl"
            ],
            "additionalProperties": false
          }
        ]
      },
      "SearchRequest": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "minLength": 1
          },
          "engine": {
            "default": "google",
            "type": "string",
            "enum": [
              "google",
              "duckduckgo",
              "mojeek",
              "brave",
              "google_ai_mode"
            ]
          },
          "country": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2
          },
          "language": {
            "type": "string",
            "pattern": "^[a-z]{2}(-[a-z]{2})?$"
          },
          "searchCount": {
            "type": "integer",
            "minimum": 1,
            "maximum": 300
          },
          "page": {
            "description": "google only: the results page to start from, 1-based, where page N is the page Google shows as N. Without searchCount the response is that one page; with it, searchCount results are collected starting from that page. page and searchCount together stay within the first 300 results. A page past Google's last result answers with no results and zeroResults true. Page N starts at Google's offset (N-1)*10, but a page holds 8-10 organic results, so separate page requests can repeat or skip a result between them; for one de-duplicated list, send a single request with searchCount instead.",
            "type": "integer",
            "minimum": 1,
            "maximum": 30
          },
          "dateRange": {
            "description": "google only: limit results to a publication window. One of \"hour\", \"day\", \"week\", \"month\" or \"year\" for the past hour through the past year, or { \"from\": \"2024-01-01\", \"to\": \"2024-06-30\" } for a custom range of ISO dates, inclusive, either end optional.",
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "hour",
                  "day",
                  "week",
                  "month",
                  "year"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "from": {
                    "type": "string",
                    "format": "date",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                  },
                  "to": {
                    "type": "string",
                    "format": "date",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                  }
                },
                "additionalProperties": false
              }
            ]
          },
          "sortBy": {
            "description": "google only: \"relevance\" (the default) or \"date\" for the newest results first.",
            "type": "string",
            "enum": [
              "relevance",
              "date"
            ]
          },
          "format": {
            "description": "google only: \"structured\" (the default, recommended) answers JSON. \"raw\" answers the Google results page as HTML (text/html), one page per request: choose it with page; searchCount does not apply. dateRange and sortBy work as they do for structured results. Billed as one search per page.",
            "type": "string",
            "enum": [
              "structured",
              "raw"
            ]
          },
          "searchType": {
            "description": "google only: the Google tab to search. \"web\" (the default) is the ordinary results page. \"videos\", \"books\" and \"forums\" answer `results`, each video with `video` (channel, platform, duration) and each book with `book` (authors, published). \"images\" answers `images`, about 100 a page with the image file's URL and size. \"shopping\" answers `products`, about 55 product cards from one page. \"places\" answers `places`, 20 businesses a page.",
            "examples": [
              "images",
              "shopping"
            ],
            "type": "string",
            "enum": [
              "web",
              "images",
              "videos",
              "shopping",
              "books",
              "places",
              "forums"
            ]
          },
          "safeSearch": {
            "description": "google only: `true` returns SafeSearch's filtered results, with explicit content removed. Off by default.",
            "type": "boolean"
          },
          "includeOmittedResults": {
            "description": "google only: `true` includes the results Google normally omits as very similar to ones already shown, such as a site's other language editions. Off by default.",
            "type": "boolean"
          },
          "autocorrect": {
            "description": "google only: `false` searches the query exactly as sent, where Google would otherwise search a corrected spelling. On by default.",
            "type": "boolean"
          },
          "restrictCountry": {
            "description": "google only: results only from pages in this country, as a two-letter code such as `FR`. Unlike `country`, which sets where the search is made from, this filters the results.",
            "type": "string",
            "minLength": 2,
            "maxLength": 2
          },
          "verbatim": {
            "description": "google only: `true` matches the query's words exactly, without synonyms or stemming. Off by default.",
            "type": "boolean"
          },
          "location": {
            "description": "google and google_ai_mode: a place name such as a city. Results or the answer are given for that place and searched from its country. `coordinates`, when also sent, set the point instead.",
            "examples": [
              "London",
              "Austin,Texas,United States",
              "Paris,FR"
            ],
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "aiOverview": {
            "description": "google only. `true` makes a second, sequential fetch to fill the AI Overview Google streams in after the page loads. It adds latency: measured 2026-09-30 to 2026-10-01, about 64% of results pages carried a streamed overview, and filling it added about 2.8 s at p50 and 5.6 s at p90. A request with `aiOverview: true` costs 2x a normal search. Off by default; an AI Overview already present in the page is returned without it.",
            "type": "boolean"
          },
          "solveCaptcha": {
            "default": true,
            "description": "Controls Web Access's captcha solver for this search. `true` by default. With `false`, the solver is disabled; the search may still return results. As on /fetch, an API key without captcha-solving permission keeps the solver disabled regardless of this setting.",
            "type": "boolean"
          },
          "coordinates": {
            "description": "google and google_ai_mode: the point results are given for, such as { \"latitude\": 30.2672, \"longitude\": -97.7431 }. radius is how precise the point is, in meters (default 5000). It takes precedence over `location`. Without either, a question that depends on where you are, such as the weather today, may be answered without a location.",
            "type": "object",
            "properties": {
              "latitude": {
                "type": "number",
                "minimum": -90,
                "maximum": 90
              },
              "longitude": {
                "type": "number",
                "minimum": -180,
                "maximum": 180
              },
              "radius": {
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 1000000
              }
            },
            "required": [
              "latitude",
              "longitude"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "query"
        ],
        "additionalProperties": false
      },
      "SearchResponse": {
        "type": "object",
        "required": [
          "results",
          "zeroResults"
        ],
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchResult"
            }
          },
          "zeroResults": {
            "type": "boolean",
            "description": "True when the engine answered normally and the query genuinely matched nothing."
          },
          "aiMode": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SearchAIMode"
              }
            ],
            "description": "Google's AI Mode answer. Present on every successful `engine: \"google_ai_mode\"` response, where `results` is empty and `zeroResults` is false; absent on every other engine."
          },
          "places": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchPlace"
            },
            "description": "The local pack, when the results page carried one, or on `searchType: \"places\"` the whole answer, 20 businesses a page. Absent otherwise, and never merged into `results`."
          },
          "images": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchImage"
            },
            "description": "On `searchType: \"images\"` the whole answer, about 100 a page; on a web search the page's Images block, whose entries carry `position`, `title`, `url` and `source` only."
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchProduct"
            },
            "description": "`searchType: \"shopping\"` only: the product cards of the one shopping page, about 55."
          },
          "entity": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SearchEntity"
              }
            ],
            "description": "The knowledge panel, when the results page carried one. Absent otherwise, and never merged into `results`."
          },
          "paging": {
            "type": "object",
            "required": [
              "pages",
              "complete",
              "stoppedBy"
            ],
            "properties": {
              "pages": {
                "type": "integer",
                "description": "Results pages that answered, each billed as one search request."
              },
              "complete": {
                "type": "boolean",
                "description": "False when a later page could not be fetched or the search's time budget ran out before `searchCount` was reached; `results` then carries what was collected. True when `searchCount` was reached, Google had no more results, the thirty-six-page cap was reached, or the first page carried no organic results (a local pack or knowledge panel alone is not paged). `stoppedBy` tells these apart."
              },
              "stoppedBy": {
                "type": "string",
                "enum": [
                  "search_count",
                  "end_of_results",
                  "page_cap",
                  "page_failed",
                  "deadline"
                ],
                "description": "Why paging stopped. `search_count`: `searchCount` results were collected. `end_of_results`: Google had no more organic results. `page_cap`: the search reached its thirty-six-page depth limit and Google may have more. `page_failed`: a later page could not be fetched. `deadline`: the time budget ran out. `complete` is false only for `page_failed` and `deadline`."
              }
            },
            "description": "How a `searchCount` request was filled. Present only when `searchCount` was sent."
          }
        }
      },
      "SearchResult": {
        "type": "object",
        "required": [
          "position",
          "title",
          "snippet",
          "displayUrl"
        ],
        "properties": {
          "position": {
            "type": "integer",
            "description": "1-based place in this response's `results`, after duplicates are removed. Restarts at 1 on every request."
          },
          "rank": {
            "type": "integer",
            "description": "Google only: the result's absolute Google rank, the offset of the page it came from plus its 1-based place on that page, so the first result of `page: 3` has rank 21. Google pages hold 8-10 organic results, so ranks can skip numbers."
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The destination, without Google's redirect or tracking. Absent when Google linked the result only through a redirect whose destination is not known; the result is still returned."
          },
          "snippet": {
            "type": "string"
          },
          "displayUrl": {
            "type": "string",
            "description": "Google's displayed URL line; empty when Google shows none."
          },
          "displayText": {
            "type": "string",
            "description": "The source line Google shows under the title, verbatim; may be a URL, engagement counts, or other text."
          },
          "source": {
            "type": "string",
            "description": "The site name Google shows beside the result, such as `Reddit · r/buildapc`."
          },
          "timestamp": {
            "type": "string"
          },
          "video": {
            "type": "object",
            "description": "`searchType: \"videos\"` only: who published the video, where it plays, and how long it runs.",
            "properties": {
              "channel": {
                "type": "string"
              },
              "platform": {
                "type": "string"
              },
              "duration": {
                "type": "string",
                "examples": [
                  "12:48"
                ]
              }
            }
          },
          "book": {
            "type": "object",
            "description": "`searchType: \"books\"` only: the authors and the publication year or date.",
            "properties": {
              "authors": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "published": {
                "type": "string",
                "examples": [
                  "1965"
                ]
              }
            }
          }
        }
      },
      "SearchPlace": {
        "type": "object",
        "required": [
          "position",
          "name"
        ],
        "properties": {
          "position": {
            "type": "integer",
            "description": "1-based rank within the local pack."
          },
          "name": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "rating": {
            "type": "number"
          },
          "reviews": {
            "type": "integer"
          },
          "address": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "hours": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "mapsUrl": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "SearchImage": {
        "type": "object",
        "required": [
          "position",
          "title"
        ],
        "properties": {
          "position": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The page the image appears on."
          },
          "source": {
            "type": "string",
            "description": "The site's name, as Google shows it."
          },
          "imageUrl": {
            "type": "string",
            "format": "uri",
            "description": "The image file itself."
          },
          "imageWidth": {
            "type": "integer"
          },
          "imageHeight": {
            "type": "integer"
          },
          "thumbnail": {
            "type": "string",
            "format": "uri",
            "description": "Google's resized copy."
          }
        }
      },
      "SearchProduct": {
        "type": "object",
        "required": [
          "position",
          "title"
        ],
        "properties": {
          "position": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "productId": {
            "type": "string",
            "description": "Google's catalog id for the product."
          },
          "price": {
            "type": "string",
            "description": "As Google shows it, currency symbol included.",
            "examples": [
              "$169.00"
            ]
          },
          "originalPrice": {
            "type": "string",
            "description": "The struck-through price, when the product is discounted."
          },
          "merchant": {
            "type": "string",
            "description": "The seller Google names first."
          },
          "moreMerchants": {
            "type": "boolean",
            "description": "True when other sellers offer the product too."
          },
          "delivery": {
            "type": "string"
          },
          "returns": {
            "type": "string"
          },
          "rating": {
            "type": "number"
          },
          "reviews": {
            "type": "integer"
          }
        }
      },
      "SearchEntity": {
        "type": "object",
        "required": [
          "title",
          "descriptionSource",
          "website",
          "attributes",
          "profiles",
          "unread"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "subtitle": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "descriptionSource": {
            "$ref": "#/components/schemas/SearchEntityLink"
          },
          "rating": {
            "type": "number"
          },
          "reviews": {
            "type": "integer"
          },
          "website": {
            "$ref": "#/components/schemas/SearchEntityLink"
          },
          "attributes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchEntityAttribute"
            }
          },
          "profiles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchEntityLink"
            }
          },
          "unread": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "SearchEntityLink": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "urlUnresolved": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Present, and `true`, when the link has no `url` because its destination could not be resolved on this read. Retrying the search usually resolves it."
          }
        }
      },
      "SearchEntityAttribute": {
        "type": "object",
        "required": [
          "label",
          "value"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "value": {
            "type": "string"
          }
        }
      },
      "SearchAIMode": {
        "type": "object",
        "required": [
          "text",
          "sources"
        ],
        "properties": {
          "text": {
            "type": "string",
            "description": "The generated answer as plain text: a block per line, list items prefixed `- `, and a table row per line with its cells joined by ` | `."
          },
          "markdown": {
            "type": "string",
            "description": "The answer as Markdown, with its headings, lists, tables and code blocks."
          },
          "blocks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchAIModeBlock"
            },
            "description": "The answer's structure in reading order: paragraphs, headings, lists, tables and code blocks."
          },
          "sources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchAIModeSource"
            },
            "description": "The pages the answer cites, in the order Google lists them. Empty when Google cited none."
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchAIModeProduct"
            },
            "description": "The products the answer recommends. Absent when it showed none."
          },
          "places": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchAIModePlace"
            },
            "description": "The places the answer names. Absent when it named none."
          },
          "videos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchAIModeVideo"
            },
            "description": "The videos the answer cites. Each is also in `sources`. Absent when it cited none."
          }
        }
      },
      "SearchAIModeSource": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "urlUnresolved": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Present, and `true`, when the link has no `url` because its destination could not be resolved on this read. Retrying the search usually resolves it."
          },
          "snippet": {
            "type": "string",
            "description": "The passage of the page the citation quotes."
          },
          "source": {
            "type": "string",
            "description": "The site's own name, such as \"Reddit\"."
          }
        }
      },
      "SearchAIModeBlock": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "paragraph",
              "heading",
              "list",
              "table",
              "code"
            ]
          },
          "text": {
            "type": "string",
            "description": "A paragraph's or heading's text, or a code block's code with its line breaks."
          },
          "level": {
            "type": "integer",
            "description": "A heading's level, 1 to 6."
          },
          "ordered": {
            "type": "boolean",
            "description": "Whether a list is numbered."
          },
          "items": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "A list's items."
          },
          "header": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "A table's column headings, when it has a header row."
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "A table's rows, one cell per column."
          },
          "language": {
            "type": "string",
            "description": "A code block's language, when the answer labelled it."
          }
        }
      },
      "SearchAIModeProduct": {
        "type": "object",
        "required": [
          "title"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "price": {
            "type": "string",
            "description": "The price as displayed, such as \"$84.99\" or \"$33.29/mo\"."
          },
          "oldPrice": {
            "type": "string",
            "description": "The price before a reduction, when the card shows one."
          },
          "merchant": {
            "type": "string",
            "description": "The seller the product card names."
          },
          "moreSellers": {
            "type": "boolean",
            "description": "True when the card says other sellers offer it too."
          },
          "rating": {
            "type": "number"
          },
          "reviews": {
            "type": "integer"
          },
          "thumbnail": {
            "type": "string",
            "format": "uri"
          },
          "productId": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Google's product page for the product."
          }
        }
      },
      "SearchAIModePlace": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "rating": {
            "type": "number"
          },
          "reviews": {
            "type": "integer"
          },
          "priceLevel": {
            "type": "string",
            "description": "Such as \"$10–20\"."
          },
          "status": {
            "type": "string",
            "description": "Opening status as displayed, such as \"Open\" or \"Closed\"."
          },
          "address": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Google's page for the place."
          }
        }
      },
      "SearchAIModeVideo": {
        "type": "object",
        "required": [
          "title"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "channel": {
            "type": "string"
          },
          "duration": {
            "type": "string",
            "description": "As displayed, such as \"7:18\"."
          },
          "thumbnail": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "SitemapRequest": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "maxPages": {
            "default": 10,
            "type": "integer",
            "minimum": 1,
            "maximum": 10000
          },
          "maxDepth": {
            "default": 2,
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          },
          "pathPrefix": {
            "type": "string"
          },
          "budgetUsd": {
            "type": "number",
            "minimum": 0.0001
          },
          "userId": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 9007199254740991
          },
          "useSitemap": {
            "default": false,
            "type": "boolean"
          }
        },
        "required": [
          "url"
        ],
        "additionalProperties": false
      },
      "SitemapJob": {
        "type": "object",
        "required": [
          "jobId",
          "domain",
          "startUrl",
          "status",
          "pagesProcessed",
          "maxDepth",
          "maxPages",
          "estimatedCostUsd"
        ],
        "properties": {
          "jobId": {
            "type": "string"
          },
          "domain": {
            "type": "string"
          },
          "startUrl": {
            "type": "string",
            "format": "uri"
          },
          "status": {
            "type": "string"
          },
          "pagesProcessed": {
            "type": "integer"
          },
          "maxDepth": {
            "type": "integer"
          },
          "maxPages": {
            "type": "integer"
          },
          "estimatedCostUsd": {
            "type": "string",
            "description": "Quote ceiling for the crawl, in USD."
          },
          "costUsd": {
            "type": [
              "string",
              "null"
            ],
            "description": "Metered spend once the job is terminal. Null while running, and for failed jobs, which bill nothing."
          },
          "createdByUserID": {
            "type": [
              "integer",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "finishedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "errorMessage": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SitemapJobList": {
        "type": "object",
        "required": [
          "jobs"
        ],
        "properties": {
          "jobs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SitemapJob"
            }
          }
        }
      },
      "SitemapJobQuote": {
        "type": "object",
        "required": [
          "jobId",
          "status",
          "estimatedCostUsd",
          "estimatedCostMinUsd",
          "estimatedPages"
        ],
        "properties": {
          "jobId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "`awaiting_approval` for a crawl that must be approved before it spends."
          },
          "estimatedCostUsd": {
            "type": "string",
            "description": "The quote CEILING, in USD. It is what gets held in escrow and caps the crawl, so it is a never-pay-more-than."
          },
          "estimatedCostMinUsd": {
            "type": "string",
            "description": "The advisory floor of the quote range, in USD."
          },
          "estimatedPages": {
            "type": "integer"
          }
        }
      },
      "SitemapJobAck": {
        "type": "object",
        "required": [
          "jobId",
          "status"
        ],
        "properties": {
          "jobId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "SitemapJobState": {
        "oneOf": [
          {
            "title": "AwaitingApproval",
            "type": "object",
            "required": [
              "jobId",
              "status",
              "estimatedCostUsd"
            ],
            "properties": {
              "jobId": {
                "type": "string"
              },
              "status": {
                "const": "awaiting_approval"
              },
              "estimatedCostUsd": {
                "type": "string"
              }
            }
          },
          {
            "title": "CompletedWithUrls",
            "description": "A completed job whose per-URL results are still available carries them inline.",
            "type": "object",
            "required": [
              "jobId",
              "status",
              "pagesProcessed",
              "costUsd",
              "urls"
            ],
            "properties": {
              "jobId": {
                "type": "string"
              },
              "status": {
                "const": "completed"
              },
              "pagesProcessed": {
                "type": "integer"
              },
              "costUsd": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "urls": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SitemapUrl"
                }
              }
            }
          },
          {
            "title": "Completed",
            "description": "A completed job whose per-URL results have expired; only the summary remains.",
            "type": "object",
            "required": [
              "jobId",
              "status",
              "pagesProcessed",
              "costUsd",
              "finishedAt"
            ],
            "properties": {
              "jobId": {
                "type": "string"
              },
              "status": {
                "const": "completed"
              },
              "pagesProcessed": {
                "type": "integer"
              },
              "costUsd": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "finishedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          },
          {
            "title": "Failed",
            "type": "object",
            "required": [
              "jobId",
              "status",
              "errorMessage",
              "costUsd",
              "finishedAt"
            ],
            "properties": {
              "jobId": {
                "type": "string"
              },
              "status": {
                "const": "failed"
              },
              "errorMessage": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "costUsd": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "finishedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          },
          {
            "title": "InProgress",
            "description": "Also the shape for the terminal `canceled` and `token_cap_exceeded` states.",
            "type": "object",
            "required": [
              "jobId",
              "status",
              "pending",
              "processed",
              "costUsd"
            ],
            "properties": {
              "jobId": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "pending": {
                "type": "integer"
              },
              "processed": {
                "type": "integer"
              },
              "costUsd": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        ]
      },
      "SitemapUrl": {
        "type": "object",
        "required": [
          "url",
          "statusCode",
          "depth",
          "isSitemap",
          "parentUrl",
          "sourceType"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "statusCode": {
            "type": "integer",
            "description": "0 when the crawler recorded no status for the page."
          },
          "depth": {
            "type": "integer"
          },
          "isSitemap": {
            "type": "boolean"
          },
          "parentUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "sourceType": {
            "type": "string"
          },
          "error": {
            "type": "string",
            "description": "Present only for a URL the crawl failed on."
          }
        }
      },
      "SitemapUrlPage": {
        "type": "object",
        "required": [
          "jobId",
          "total",
          "urls"
        ],
        "properties": {
          "jobId": {
            "type": "string"
          },
          "total": {
            "type": "integer",
            "description": "Total discovered URLs, not the size of this page."
          },
          "urls": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SitemapUrl"
            }
          }
        }
      },
      "SitemapConflict": {
        "type": "object",
        "required": [
          "jobId",
          "status",
          "error"
        ],
        "properties": {
          "jobId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        }
      },
      "SitemapInsufficientFunds": {
        "type": "object",
        "required": [
          "jobId",
          "status",
          "estimatedCostUsd",
          "error"
        ],
        "properties": {
          "jobId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "estimatedCostUsd": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        }
      },
      "BrowserContextCreateRequest": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          }
        },
        "additionalProperties": false
      },
      "BrowserContext": {
        "type": "object",
        "required": [
          "id",
          "name",
          "status",
          "sizeBytes",
          "failureReason",
          "latestSaveOperation",
          "lastSavedAt",
          "lastUsedAt",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "EMPTY",
              "IN_USE",
              "UPLOADING",
              "READY",
              "FAILED"
            ]
          },
          "sizeBytes": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Size of the stored profile archive."
          },
          "failureReason": {
            "type": [
              "string",
              "null"
            ]
          },
          "latestSaveOperation": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "id",
              "status",
              "failureReason",
              "completedAt"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": [
                  "PENDING",
                  "COMMITTED",
                  "FAILED",
                  "EXPIRED",
                  "SUPERSEDED"
                ]
              },
              "failureReason": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "completedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          },
          "lastSavedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the profile data was last durable, as against `lastUsedAt`, which is activity."
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BrowserContextList": {
        "type": "object",
        "required": [
          "contexts"
        ],
        "properties": {
          "contexts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BrowserContext"
            }
          }
        }
      },
      "BrowserContextDeleteAccepted": {
        "type": "object",
        "required": [
          "id",
          "status",
          "deleted"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "const": "DELETING"
          },
          "deleted": {
            "const": false
          }
        }
      },
      "BrowserContextDeleted": {
        "type": "object",
        "required": [
          "id",
          "deleted"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "deleted": {
            "const": true
          }
        }
      },
      "BrowserSessionCreateRequest": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "proxy": {
            "type": "string",
            "enum": [
              "standard",
              "premium"
            ]
          },
          "countryCode": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2
          },
          "contextId": {
            "type": "string",
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
          },
          "persist": {
            "type": "boolean"
          },
          "record": {
            "type": "boolean"
          },
          "browserVersion": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[1-9][0-9]{2}$"
              },
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            ]
          }
        },
        "additionalProperties": false
      },
      "BrowserSession": {
        "type": "object",
        "required": [
          "id",
          "status",
          "contextId",
          "persist",
          "proxy",
          "record",
          "frameCount",
          "attempts",
          "closeCode",
          "closeReason",
          "createdAt",
          "startedAt",
          "endedAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^ses_[0-9a-f]{32}$"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "connecting",
              "running",
              "ended",
              "failed",
              "expired"
            ],
            "description": "`expired` is a created session that was never connected within its ten minutes."
          },
          "connectUrl": {
            "type": "string",
            "description": "Present while `pending`: the `/wss` URL that connects this session, once. Send the API key as the `Authorization` header."
          },
          "connectBy": {
            "type": "string",
            "format": "date-time",
            "description": "Present while `pending`: the session expires unconnected after this."
          },
          "contextId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "persist": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "proxy": {
            "type": "object",
            "required": [
              "tier",
              "countryCode",
              "provider",
              "zone"
            ],
            "properties": {
              "tier": {
                "type": "string",
                "enum": [
                  "standard",
                  "premium"
                ]
              },
              "countryCode": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "provider": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The exit provider the session was routed through, once it connected."
              },
              "zone": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "record": {
            "type": "boolean",
            "description": "Whether a screencast replay is recorded."
          },
          "browserVersion": {
            "type": "string",
            "pattern": "^[1-9][0-9]{2}$",
            "description": "Present when the session asked for a Chrome build."
          },
          "frameCount": {
            "type": "integer",
            "description": "Replay frames stored so far."
          },
          "attempts": {
            "type": "integer",
            "description": "Browser launches it took to connect; capacity retries add one each."
          },
          "closeCode": {
            "type": [
              "integer",
              "null"
            ]
          },
          "closeReason": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "startedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "endedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "BrowserSessionDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BrowserSession"
          },
          {
            "type": "object",
            "required": [
              "files"
            ],
            "properties": {
              "files": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/BrowserSessionFile"
                }
              }
            }
          }
        ]
      },
      "BrowserSessionList": {
        "type": "object",
        "required": [
          "sessions",
          "limit",
          "offset"
        ],
        "properties": {
          "sessions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BrowserSession"
            }
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          }
        }
      },
      "BrowserSessionFile": {
        "type": "object",
        "required": [
          "name",
          "sizeBytes",
          "contentType",
          "sha256",
          "createdAt"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "sizeBytes": {
            "type": "integer"
          },
          "contentType": {
            "type": "string"
          },
          "sha256": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BrowserSessionFileList": {
        "type": "object",
        "required": [
          "files",
          "expiresAt"
        ],
        "properties": {
          "files": {
            "type": "array",
            "items": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/BrowserSessionFile"
                },
                {
                  "type": "object",
                  "required": [
                    "url"
                  ],
                  "properties": {
                    "url": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Short-lived download URL."
                    }
                  }
                }
              ]
            }
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the download URLs stop working."
          }
        }
      },
      "BrowserSessionReplay": {
        "type": "object",
        "required": [
          "id",
          "status",
          "frameCount",
          "format",
          "chunks",
          "expiresAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "frameCount": {
            "type": "integer"
          },
          "format": {
            "const": "ndjson",
            "description": "Each chunk is newline-delimited JSON, one frame per line: `{t, target, data, width, height}`, where `t` is epoch ms, `target` names the tab, and `data` is a base64 JPEG."
          },
          "chunks": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "index",
                "url"
              ],
              "properties": {
                "index": {
                  "type": "integer"
                },
                "url": {
                  "type": "string"
                }
              }
            }
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the chunk URLs stop working."
          }
        }
      },
      "ErrorResponse": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "statusCode": {
            "type": "number"
          },
          "message": {
            "type": "string"
          },
          "traceId": {
            "type": "string"
          },
          "issues": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "field",
                "message"
              ],
              "additionalProperties": false
            }
          },
          "errorType": {
            "type": "string"
          },
          "data": {},
          "headers": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              ]
            }
          },
          "finalUrl": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "additionalProperties": false
      },
      "SimpleError": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "DomainDenied": {
        "type": "object",
        "required": [
          "reason"
        ],
        "properties": {
          "reason": {
            "type": "string"
          }
        }
      }
    }
  }
}