{"openapi":"3.0.0","paths":{"/v1/web/scrape":{"post":{"description":"Fetch a single URL and return it in the formats you ask for. Waits for the result by default, returning a job id if it runs long; set `async` to always return a job id immediately.","operationId":"scrape","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeRequestDto"}}}},"responses":{"200":{"description":"The scraped page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeResponseDto"}}}},"201":{"description":"The scrape is running; poll the job id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeAcceptedDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Scrape a URL","tags":["Scrape"]}},"/v1/web/markdown":{"post":{"description":"Fetch a URL and return clean Markdown of its main content.","operationId":"markdown","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeFormatRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeResponseDto"}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeAcceptedDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Scrape to Markdown","tags":["Scrape"]}},"/v1/web/html":{"post":{"description":"Fetch a URL and return its cleaned main-content HTML.","operationId":"html","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeFormatRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeResponseDto"}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeAcceptedDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Scrape to HTML","tags":["Scrape"]}},"/v1/web/raw-html":{"post":{"description":"Fetch a URL and return its unmodified page HTML.","operationId":"rawHtml","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeFormatRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeResponseDto"}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeAcceptedDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Scrape raw HTML","tags":["Scrape"]}},"/v1/web/links":{"post":{"description":"Fetch a URL and return its internal and external links.","operationId":"links","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeFormatRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeResponseDto"}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeAcceptedDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Get a page's links","tags":["Scrape"]}},"/v1/web/structured":{"post":{"description":"Fetch a URL and return the page's own machine-authored structured data (JSON-LD, microdata, OpenGraph, RDFa), normalised.","operationId":"structured","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeFormatRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeResponseDto"}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeAcceptedDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Get structured data","tags":["Scrape"]}},"/v1/web/scrape/{id}":{"get":{"description":"Poll a scrape started with `async` (or one that ran past the synchronous wait).","operationId":"status","parameters":[{"name":"id","required":true,"in":"path","description":"The job id returned by the scrape call.","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeStatusResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Get scrape job status","tags":["Scrape"]}},"/v1/web/brand":{"get":{"description":"Everything needed to render a company: logos that suit light and dark backgrounds, its real colours, name, description and social presence. Resolved on the spot if we have never seen the domain, and served from storage after that. Every field states whether the company declared it or we harvested it.","operationId":"get","parameters":[{"name":"domain","required":true,"in":"query","description":"Domain to resolve. A URL works too.","schema":{"example":"stripe.com","type":"string"}}],"responses":{"200":{"description":"The resolved brand.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Resolve a brand","tags":["Brand"]},"post":{"description":"The same lookup for up to 50 domains at once. Only resolved brands are billed.","operationId":"batch","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandBatchDto"}}}},"responses":{"201":{"description":"One entry per requested domain, in the order you sent them.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandBatchResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Resolve many brands","tags":["Brand"]}},"/v1/web/brand/logo":{"get":{"description":"The one asset most callers want, without the rest of the record: a direct image URL for the company's mark, chosen for the background you name. Cheaper than a full brand resolve. The image itself is public and immutable, so the URL can be embedded anywhere.","operationId":"logo","parameters":[{"name":"domain","required":true,"in":"query","description":"Domain to fetch the logo for. A URL works too.","schema":{"example":"stripe.com","type":"string"}},{"name":"theme","required":false,"in":"query","description":"The background you are drawing on. `auto` prefers a single-colour mark.","schema":{"default":"light","type":"string","enum":["light","dark","auto"]}},{"name":"type","required":false,"in":"query","description":"The square mark, or the full wordmark.","schema":{"default":"icon","type":"string","enum":["icon","wordmark"]}}],"responses":{"200":{"description":"The chosen logo, or null when we have no mark for the domain.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandLogoResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Get a company logo","tags":["Brand"]}},"/v1/web/brand/search":{"get":{"description":"Find brands we already hold by company name or domain, so you can turn what a user typed into a domain and then resolve it. Returns the domain, name, primary logo and primary colour — enough to render a picker. Never resolves a new domain, and is not billed.","operationId":"search","parameters":[{"name":"query","required":true,"in":"query","description":"Company name or domain to search for.","schema":{"example":"stripe","type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"default":10,"example":10,"type":"number"}}],"responses":{"200":{"description":"Matching brands, best match first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandSearchResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Search brands","tags":["Brand"]}},"/v1/web/styleguide":{"get":{"description":"The colours, type scale, corner radius and button styling a site actually paints, read from computed styles in a real browser — so a value defined through four layers of CSS variables comes back as the hex it resolved to. Colours are given by role (background, surface, text, accent) with contrast ratios, so they drop into a theme without guesswork. A render every time, which is why it costs more than a brand lookup; cached for weeks after the first call.","operationId":"get","parameters":[{"name":"domain","required":true,"in":"query","description":"Domain to read the design system from.","schema":{"example":"stripe.com","type":"string"}}],"responses":{"200":{"description":"The design system.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StyleguideResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Read a company's design system","tags":["Brand"]}},"/v1/web/images":{"post":{"description":"Harvest all images from a page with their metadata.","operationId":"images","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImagesRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImagesResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Harvest a page's images","tags":["Media"]}},"/v1/web/screenshot":{"post":{"description":"Capture a full-page PNG screenshot of a rendered page.","operationId":"screenshot","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreenshotRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreenshotResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Screenshot a page","tags":["Media"]}},"/v1/web/logo/{domain}":{"get":{"description":"The image bytes for a domain, ready to drop into an `<img>` tag. Authenticated with a publishable key in the `token` parameter, so it is safe to put in a browser. A domain we have not seen yet answers with a monogram immediately and the real logo on the next request.","operationId":"serve","parameters":[{"name":"domain","required":true,"in":"path","schema":{"type":"string"}},{"name":"fallback","required":false,"in":"query","schema":{"enum":["monogram","404","transparent"],"type":"string"}},{"name":"type","required":false,"in":"query","schema":{"enum":["icon","wordmark"],"type":"string"}},{"name":"theme","required":false,"in":"query","schema":{"enum":["light","dark","auto"],"type":"string"}},{"name":"size","required":false,"in":"query","description":"Longest edge in pixels. Bounds the placeholder; a stored logo is served as-is.","schema":{}},{"name":"token","required":true,"in":"query","description":"Your publishable key.","schema":{}}],"responses":{"200":{"description":"The logo."},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Serve a company logo","tags":["Logo"]}},"/v1/web/map":{"post":{"description":"Quickly enumerate a site's URLs without scraping them. Returns synchronously and costs one credit.","operationId":"mapUrls","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapRequestDto"}}}},"responses":{"200":{"description":"The discovered URLs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Map a site","tags":["Crawl & batch"]}},"/v1/web/crawl":{"post":{"description":"Discover and scrape a whole site as one asynchronous job. Returns a crawl id immediately; poll it or register a webhook. One credit per page scraped.","operationId":"startCrawl","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrawlRequestDto"}}}},"responses":{"201":{"description":"The crawl was accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrawlAcceptedDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Start a crawl","tags":["Crawl & batch"]}},"/v1/web/batch":{"post":{"description":"Scrape an explicit list of URLs as one asynchronous job. Returns a batch id immediately; poll it or register a webhook. One credit per URL scraped.","operationId":"startBatch","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRequestDto"}}}},"responses":{"201":{"description":"The batch was accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchAcceptedDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Start a batch","tags":["Crawl & batch"]}},"/v1/web/crawl/{id}":{"get":{"description":"Poll a crawl for its progress and per-page results.","operationId":"crawlStatus","parameters":[{"name":"id","required":true,"in":"path","description":"The crawl id returned when the crawl started.","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrawlStatusEnvelopeDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Get crawl status","tags":["Crawl & batch"]}},"/v1/web/batch/{id}":{"get":{"description":"Poll a batch for its progress and per-URL results.","operationId":"batchStatus","parameters":[{"name":"id","required":true,"in":"path","description":"The batch id returned when the batch started.","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrawlStatusEnvelopeDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Get batch status","tags":["Crawl & batch"]}},"/v1/web/crawl/{id}/deliveries":{"get":{"description":"Every webhook callback we've attempted for this crawl, with its status, attempt count, and last response — so you can see whether and why a delivery failed.","operationId":"crawlDeliveries","parameters":[{"name":"id","required":true,"in":"path","description":"The crawl id.","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveriesResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"List webhook deliveries for a crawl","tags":["Crawl & batch"]}},"/v1/web/batch/{id}/deliveries":{"get":{"description":"Every webhook callback we've attempted for this batch, with its status, attempt count, and last response — so you can see whether and why a delivery failed.","operationId":"batchDeliveries","parameters":[{"name":"id","required":true,"in":"path","description":"The batch id.","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveriesResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"List webhook deliveries for a batch","tags":["Crawl & batch"]}},"/v1/web/search":{"post":{"description":"Search the web for a query and get back ranked results: title, url and snippet. Costs 1 credit. Set `scrapeResults` to true to also fetch each result as clean data, which costs 1 additional credit per page scraped.","operationId":"run","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequestDto"}}}},"responses":{"200":{"description":"The ranked search results.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Search the web","tags":["Search"]}},"/v1/web/extract":{"post":{"description":"Pull schema-shaped JSON out of one or many pages in a single call. An LLM maps each page onto your schema and/or prompt. Point at a single page, a list, or a crawl scope with a trailing `/*` wildcard; optionally let web search find extra source pages, return per-field confidence with the source passage behind each value, and merge everything into one deduplicated collection of entities. Charged per page that returns data.","operationId":"run","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractRequestDto"}}}},"responses":{"200":{"description":"The extracted data.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractResponseDto"}}}},"400":{"description":"The request body or query failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"url must be a valid URL"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"401":{"description":"The X-API-Key header is missing, malformed, or names a key that no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing X-API-Key header"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"402":{"description":"The workspace has no credits left for this request. Nothing was charged and nothing was fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INSUFFICIENT_CREDITS","message":"Insufficient credits"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"403":{"description":"The key is valid but the workspace may not make this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"WORKSPACE_BANNED","message":"This workspace has been suspended and cannot make API requests."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"404":{"description":"No such job, or the id belongs to another workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Job not found"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"429":{"description":"The workspace exceeded its per-minute request limit. Read the RateLimit headers, or Retry-After on this response, and retry after the window resets.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Prefer this over a fixed backoff.","schema":{"type":"integer","example":17}},"RateLimit":{"description":"Requests remaining (r) and seconds until the window resets (t).","schema":{"type":"string","example":"\"workspace\";r=0;t=17"}},"RateLimit-Policy":{"description":"The quota (q) for your plan and the window it applies over (w), in seconds.","schema":{"type":"string","example":"\"workspace\";q=600;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"TOO_MANY_REQUESTS","message":"Rate limit exceeded for this workspace and plan."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"500":{"description":"Unexpected server error. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"INTERNAL_SERVER_ERROR","message":"Internal server error"},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}},"503":{"description":"A dependency needed for the requested formats is unavailable. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebError"},"example":{"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The summary and json formats are not available."},"meta":{"requestId":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}}}}},"summary":"Extract structured data from URLs","tags":["Extract"]}}},"info":{"title":"Hydrafetch API","description":"Hydrafetch is a web data API for developers and agents. Send a URL and get back clean Markdown, the page's own structured data, schema-shaped JSON, links, or a summary, with the navigation, banners and boilerplate stripped out. Scrape one page, crawl a whole site, run a search, or extract to a schema, all through one API with one response shape. Every call costs one credit a page whatever it took to fetch, and failures are never billed.\n\nPoint us at a whole site and get every page. Ask a question and get answers with per-field\nconfidence and the passage each value came from. You describe the outcome you want — the\npipeline decides how to get it.\n\n## Authentication\n\nEvery request is authenticated with your API key in the `X-API-Key` header. Keys are scoped to a\nworkspace and carry its credit balance.\n\n## Credits\n\nCalls are billed in credits and charged only on success. A standard scrape is one credit; richer\nformats and the extraction tier cost more. Each response reports what it consumed.\n\n## Conventions\n\nAll timestamps are UTC ISO 8601. Long-running jobs (crawl, batch) return a job id you poll, or a\nwebhook you register.\n\n## Errors\n\nEvery failure returns the same shape, whatever the status:\n\n```json\n{ \"success\": false, \"error\": { \"code\": \"INSUFFICIENT_CREDITS\", \"message\": \"Insufficient credits\" },\n  \"meta\": { \"requestId\": \"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c\" } }\n```\n\nBranch on `error.code`, which is stable. `error.message` is written for a person and may be\nreworded without notice. Validation failures add `error.details`. Quote `meta.requestId` when\nasking us about a specific failure. Every operation documents the codes it can return.\n\n## Rate limits\n\nLimits are per workspace, not per key, over a 60 second window, and the ceiling comes from your\nplan. Every response carries the IETF RateLimit header fields so you can self-throttle rather\nthan discovering the limit by hitting it:\n\n```http\nRateLimit-Policy: \"workspace\";q=600;w=60\nRateLimit: \"workspace\";r=599;t=42\n```\n\n`q` is the quota, `w` the window in seconds, `r` the requests remaining and `t` the seconds until\nthe window resets. A 429 also carries `Retry-After` in seconds; wait that long rather than\nretrying immediately. The older `X-RateLimit-Limit`, `X-RateLimit-Remaining` and\n`X-RateLimit-Reset` headers are still sent and mean the same thing.\n\n## Versioning and deprecation\n\nThe version is in the path: every endpoint on this API lives under `/v1/`. Within a version we\nonly make additive changes — new endpoints, new optional parameters, new fields in a response.\nAdding a field to a response is not a breaking change, so parse defensively and ignore what you\ndo not recognise.\n\nAnything that would break an existing integration ships under a new version path instead. When an\nendpoint or a version is retired, the responses say so before it stops working:\n\n```http\nDeprecation: @1780272000\nSunset: Sat, 01 May 2027 00:00:00 GMT\nLink: <https://docs.hydrafetch.com/changelog>; rel=\"deprecation\"\n```\n\n`Deprecation` (RFC 9745) marks when the endpoint became deprecated, `Sunset` (RFC 8594) when it\nstops responding, and the `deprecation` link relation points at what to move to. Nothing on this\nAPI is deprecated today, so you will not see these headers yet. Watch for them rather than for an\nannouncement: the headers are the notice, and the linked changelog carries what to move to.","version":"1.0","contact":{"name":"Hydrafetch","url":"https://hydrafetch.com","email":"support@hydrafetch.com"}},"tags":[{"name":"Scrape","description":"Turn one URL into clean, LLM-ready content. Ask for Markdown, HTML, links, or the page’s own structured data, and poll a job id when a fetch runs long."},{"name":"Crawl & batch","description":"Whole sites rather than single pages. Map every URL, crawl with depth and path rules, batch a list you already have, and read the webhook deliveries for either."},{"name":"Search","description":"Search the web and get the ranked results back already scraped, so an agent has content to cite rather than links to fetch."},{"name":"Extract","description":"Pull schema-shaped JSON out of one or many pages, with optional per-field confidence and the source passage behind each value."},{"name":"Brand","description":"Resolve a domain into the company ready to render: logos for light and dark, the palette ranked by how the site uses it, fonts, socials, and the design system behind them."},{"name":"Media","description":"Images and screenshots from a page, with source and alt text, or a rendered capture of the page as it appears."}],"servers":[{"url":"https://api.hydrafetch.com","description":"Production"}],"components":{"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"LocationDto":{"type":"object","properties":{"country":{"type":"string","example":"us","description":"ISO 3166 alpha-2 country to fetch the page as if from."},"languages":{"example":["en-US","en"],"description":"Preferred content languages, most-preferred first.","type":"array","items":{"type":"string"}}}},"JsonOptionsDto":{"type":"object","properties":{"schema":{"type":"object","additionalProperties":true,"description":"JSON Schema describing the shape you want the `json` format to return."},"prompt":{"type":"string","maxLength":2000,"example":"Extract the product name, price, and availability.","description":"Natural-language instruction for the `json` format. Use with or instead of a schema."}}},"ScrapeRequestDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com","description":"The URL to scrape. Must be http(s)."},"maxAge":{"type":"number","minimum":0,"maximum":604800000,"description":"Serve from cache if a capture of this URL is younger than this many milliseconds. Omit for the default 24h window; 0 always fetches fresh. Capped at 7 days."},"cacheOnly":{"type":"boolean","description":"Only serve from cache. If there is no fresh cached copy, return 404 instead of fetching."},"storeInCache":{"type":"boolean","description":"Persist the capture for later re-extraction. Default true."},"preferStructure":{"type":"boolean","description":"Preserve document structure (headings, lists, tables) over prose density — good for marketing and service pages. Default off."},"async":{"type":"boolean","description":"Return a job id immediately instead of waiting for the result. Poll GET /v1/web/scrape/{id}. Opt in only: a synchronous call never degrades to a job id on its own, so you get a page or an error, not two response shapes."},"onlyMainContent":{"type":"boolean","description":"Return only the main content, dropping nav/boilerplate. Default true."},"includeTags":{"maxItems":50,"example":["article","main"],"description":"CSS selectors to keep. When set, only matching elements are considered.","type":"array","items":{"type":"string"}},"excludeTags":{"maxItems":50,"example":[".ad","#comments"],"description":"CSS selectors to strip before extraction.","type":"array","items":{"type":"string"}},"removeBase64Images":{"type":"boolean","description":"Strip inline base64 images from the output. Default true."},"blockAds":{"type":"boolean","description":"Remove common ad and tracking elements. Default true."},"includeLinks":{"type":"boolean","description":"Keep inline links in the markdown. Default true — a bare `Read the guide` is worth less to a model than one it can follow. Turn off for the densest possible prose."},"waitFor":{"type":"number","minimum":0,"maximum":30000,"description":"Extra milliseconds to let the page settle before capture."},"timeout":{"type":"number","minimum":1000,"maximum":120000,"description":"Overall time budget for the request, in milliseconds."},"location":{"$ref":"#/components/schemas/LocationDto"},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra request headers to send when fetching the page."},"formats":{"type":"array","example":["markdown"],"description":"What to return. Omit for Markdown only. `structured` is the page's own data (no LLM, cheapest); `summary` and `json` are LLM-backed and cost more.","items":{"type":"string","enum":["markdown","html","rawHtml","links","structured","summary","json","brand"]}},"jsonOptions":{"description":"Schema and/or prompt for the `json` format. One is required when `json` is requested.","allOf":[{"$ref":"#/components/schemas/JsonOptionsDto"}]}},"required":["url"]},"WebScrapeMetadataDto":{"type":"object","properties":{"title":{"type":"object","nullable":true,"example":"Example Domain","description":"The page title."},"structure":{"type":"string","enum":["markdown","plain"],"example":"markdown","description":"Whether the content carries markdown structure (headings, lists, emphasis) or is plain prose. `plain` is not an error — the default extractor optimises for capturing every word and wins on listing and forum pages. If you need the structure, re-request with `preferStructure: true`."},"pageType":{"type":"string","example":"article","description":"Coarse page classification (e.g. article, listing, forum, docs)."},"wordCount":{"type":"number","example":214,"description":"Word count of the extracted main content."},"description":{"type":"object","nullable":true,"example":"A short summary of the page, as published by the page itself.","description":"The page's own description (meta description / og:description)."},"language":{"type":"object","nullable":true,"example":"en","description":"The language the page declares."},"author":{"type":"object","nullable":true,"example":"Jane Doe","description":"The declared author."},"siteName":{"type":"object","nullable":true,"example":"Example Blog","description":"The declared site name."},"publishedTime":{"type":"object","nullable":true,"example":"2026-01-05","description":"When the page says it was published (ISO 8601)."},"image":{"type":"object","nullable":true,"example":"https://example.com/cover.png","description":"The page's lead image (og:image)."}},"required":["title","structure","pageType","wordCount","description","language","author","siteName","publishedTime","image"]},"WebUsageDto":{"type":"object","properties":{"creditsUsed":{"type":"number","example":1,"description":"Credits this call consumed. Charged only on success."},"creditsRemaining":{"type":"number","example":4999,"description":"Credits left in your workspace's balance after this call."},"freshness":{"type":"string","enum":["cache","fresh"],"example":"fresh","description":"Whether the result was served from cache or freshly fetched."}},"required":["creditsUsed","creditsRemaining","freshness"]},"WebQualityDto":{"type":"object","properties":{"confidence":{"type":"number","example":0.94,"minimum":0,"maximum":1,"description":"How trustworthy the extraction is, from 0 to 1. High when independent checks corroborate substantial content; near zero when the page yielded almost nothing."},"complete":{"type":"boolean","example":true,"description":"Whether the result captured the bulk of the content available on the page. False when the result looks thin or truncated."},"blocked":{"type":"boolean","example":false,"description":"Whether the page appeared to be behind a challenge or bot wall."}},"required":["confidence","complete","blocked"]},"WebLinksDto":{"type":"object","properties":{"internal":{"description":"Links pointing to the same site.","type":"array","items":{"type":"string"}},"external":{"description":"Links pointing to other sites.","type":"array","items":{"type":"string"}}},"required":["internal","external"]},"WebStructuredEntityDto":{"type":"object","properties":{"type":{"type":"string","example":"Product","description":"The schema.org type of the entity."},"source":{"type":"string","enum":["json-ld","microdata","rdfa","opengraph"],"description":"Which structured-data syntax the entity came from."},"properties":{"type":"object","additionalProperties":true,"description":"The entity's properties, as published."}},"required":["type","source","properties"]},"WebStructuredDataDto":{"type":"object","properties":{"entities":{"description":"The page's own structured data, normalised into one deduplicated list of typed entities.","type":"array","items":{"$ref":"#/components/schemas/WebStructuredEntityDto"}},"jsonLd":{"description":"Raw JSON-LD blocks, as found on the page.","type":"array","items":{"type":"object"}},"microdata":{"description":"Raw microdata items.","type":"array","items":{"type":"object"}},"opengraph":{"description":"Raw OpenGraph/Twitter-card tags.","type":"array","items":{"type":"object"}},"rdfa":{"description":"Raw RDFa items.","type":"array","items":{"type":"object"}},"appState":{"description":"Names of embedded framework app-state blocks detected on the page.","type":"array","items":{"type":"string"}}},"required":["entities","jsonLd","microdata","opengraph","rdfa","appState"]},"WebScrapeDataDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com","description":"The URL you requested."},"finalUrl":{"type":"string","example":"https://example.com/","description":"The final URL after any redirects."},"redirected":{"type":"boolean","example":false,"description":"Whether the origin redirected: true when `finalUrl` differs from the URL you requested. Explicit so a page with no redirect is distinguishable from one whose redirect was not tracked."},"status":{"type":"number","example":200,"description":"HTTP status of the fetched page."},"cached":{"type":"boolean","example":false,"description":"Whether this result was served from cache."},"warning":{"type":"string","description":"Set when the page was returned with a caveat (e.g. partial content)."},"metadata":{"$ref":"#/components/schemas/WebScrapeMetadataDto"},"usage":{"$ref":"#/components/schemas/WebUsageDto"},"quality":{"description":"Per-page extraction quality signals.","allOf":[{"$ref":"#/components/schemas/WebQualityDto"}]},"markdown":{"type":"string","description":"Clean Markdown of the main content. Returned when `markdown` is requested."},"html":{"type":"string","description":"Cleaned main-content HTML. Returned when `html` is requested."},"rawHtml":{"type":"string","description":"The unmodified page HTML. Returned when `rawHtml` is requested."},"links":{"description":"Returned when `links` is requested.","allOf":[{"$ref":"#/components/schemas/WebLinksDto"}]},"structured":{"description":"Returned when `structured` is requested.","allOf":[{"$ref":"#/components/schemas/WebStructuredDataDto"}]},"summary":{"type":"string","description":"A concise factual summary. Returned when `summary` is requested (LLM-backed)."},"json":{"type":"object","additionalProperties":true,"description":"Schema-shaped JSON. Returned when `json` is requested (LLM-backed)."}},"required":["url","finalUrl","redirected","status","cached","metadata"]},"ScrapeResponseDto":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebScrapeDataDto"}},"required":["data"]},"ScrapeAcceptedDto":{"type":"object","properties":{"jobId":{"type":"string","example":"019f3c09-6fae-740f-9257-10c2b6af7f43","description":"Poll this job id at GET /v1/web/scrape/{id}."},"status":{"type":"string","enum":["queued"],"example":"queued","description":"Only returned when the request asked for `async: true`."}},"required":["jobId","status"]},"ScrapeFormatRequestDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com","description":"The URL to scrape. Must be http(s)."},"maxAge":{"type":"number","minimum":0,"maximum":604800000,"description":"Serve from cache if a capture of this URL is younger than this many milliseconds. Omit for the default 24h window; 0 always fetches fresh. Capped at 7 days."},"cacheOnly":{"type":"boolean","description":"Only serve from cache. If there is no fresh cached copy, return 404 instead of fetching."},"storeInCache":{"type":"boolean","description":"Persist the capture for later re-extraction. Default true."},"preferStructure":{"type":"boolean","description":"Preserve document structure (headings, lists, tables) over prose density — good for marketing and service pages. Default off."},"async":{"type":"boolean","description":"Return a job id immediately instead of waiting for the result. Poll GET /v1/web/scrape/{id}. Opt in only: a synchronous call never degrades to a job id on its own, so you get a page or an error, not two response shapes."},"onlyMainContent":{"type":"boolean","description":"Return only the main content, dropping nav/boilerplate. Default true."},"includeTags":{"maxItems":50,"example":["article","main"],"description":"CSS selectors to keep. When set, only matching elements are considered.","type":"array","items":{"type":"string"}},"excludeTags":{"maxItems":50,"example":[".ad","#comments"],"description":"CSS selectors to strip before extraction.","type":"array","items":{"type":"string"}},"removeBase64Images":{"type":"boolean","description":"Strip inline base64 images from the output. Default true."},"blockAds":{"type":"boolean","description":"Remove common ad and tracking elements. Default true."},"includeLinks":{"type":"boolean","description":"Keep inline links in the markdown. Default true — a bare `Read the guide` is worth less to a model than one it can follow. Turn off for the densest possible prose."},"waitFor":{"type":"number","minimum":0,"maximum":30000,"description":"Extra milliseconds to let the page settle before capture."},"timeout":{"type":"number","minimum":1000,"maximum":120000,"description":"Overall time budget for the request, in milliseconds."},"location":{"$ref":"#/components/schemas/LocationDto"},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra request headers to send when fetching the page."}},"required":["url"]},"ScrapeStatusResponseDto":{"type":"object","properties":{"status":{"type":"string","enum":["waiting","active","completed","failed"],"example":"completed","description":"Job state."},"data":{"description":"Present when completed.","allOf":[{"$ref":"#/components/schemas/WebScrapeDataDto"}]},"error":{"type":"string","description":"Present when the job failed."}},"required":["status"]},"BrandFieldProvenanceDto":{"type":"object","properties":{"source":{"type":"string","enum":["declared","harvested","inferred","external"],"example":"declared","description":"`declared` the site said it in its own markup. `harvested` we processed an asset or read its CSS. `inferred` a model produced it from the page. `external` an enrichment source rather than the site."},"confidence":{"type":"number","example":0.9,"minimum":0,"maximum":1}},"required":["source"]},"BrandNaicsSectorDto":{"type":"object","properties":{"code":{"type":"string","example":"52"},"title":{"type":"string","example":"Finance and Insurance"}},"required":["code","title"]},"BrandNaicsDto":{"type":"object","properties":{"code":{"type":"string","example":"5223"},"title":{"type":"string","example":"Activities Related to Credit Intermediation"},"level":{"type":"string","enum":["sector","industry_group","national_industry"],"example":"industry_group","description":"How specific the answer is. `industry_group` is the 4-digit level, `national_industry` the 6-digit one."},"sector":{"$ref":"#/components/schemas/BrandNaicsSectorDto"},"confidence":{"type":"number","example":0.8,"minimum":0,"maximum":1,"description":"How much evidence the classification found, not a model's self-report."}},"required":["code","title","level","sector","confidence"]},"BrandResolutionDto":{"type":"object","properties":{"width":{"type":"number","example":180},"height":{"type":"number","example":180},"aspectRatio":{"type":"number","example":1,"description":"Width over height — what a caller reserves layout space with."}},"required":["width","height","aspectRatio"]},"BrandColorDto":{"type":"object","properties":{"hex":{"type":"string","example":"#533afd"},"name":{"type":"string","example":"Indigo","description":"Nearest CSS colour name, so a swatch reads as something and not only as six digits."},"weight":{"type":"number","example":0.42,"description":"How much the site itself uses it — the ranking that makes this the brand's colour."},"role":{"type":"string","enum":["primary","accent","background","text"],"example":"primary"}},"required":["hex","weight"]},"BrandAssetDto":{"type":"object","properties":{"kind":{"type":"string","enum":["wordmark","symbol","favicon","backdrop"],"example":"symbol","description":"What kind of mark this is."},"variant":{"type":"string","enum":["light","dark","mono"],"example":"light","description":"Which background the asset is legible on. `mono` is a single-colour mark that works on both."},"url":{"type":"string","example":"https://media.hydrafetch.com/brand/a0/a07c2695173dde0a1ffa.svg","description":"Public and immutable, so it can be embedded anywhere."},"format":{"type":"string","example":"svg"},"resolution":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/BrandResolutionDto"}]},"colors":{"description":"The colours in the asset itself. A logo's own palette is the brand's, by definition.","type":"array","items":{"$ref":"#/components/schemas/BrandColorDto"}},"blurhash":{"type":"object","nullable":true,"example":"LmGk_aoh4sWHohWEWDt506WD?Sod","description":"Tiny placeholder hash, so a client can render something before the image lands."}},"required":["kind","variant","url","format","resolution","colors","blurhash"]},"BrandFontDto":{"type":"object","properties":{"family":{"type":"string","example":"Sohne"},"weight":{"type":"number","description":"How much of the site's type this face sets, 1 for the most-used one.","example":1},"role":{"type":"string","description":"Absent when the page does not say which the face is.","enum":["heading","body"],"example":"body"}},"required":["family","weight"]},"BrandSocialDto":{"type":"object","properties":{"platform":{"type":"string","example":"x"},"url":{"type":"string","example":"https://x.com/stripe"},"handle":{"type":"string","example":"stripe","description":"The account name, without the `@`."}},"required":["platform","url"]},"BrandLinksDto":{"type":"object","properties":{"pricing":{"type":"string","example":"https://stripe.com/pricing"},"blog":{"type":"string","example":"https://stripe.com/blog"},"careers":{"type":"string","example":"https://stripe.com/jobs"},"contact":{"type":"string","example":"https://stripe.com/contact"},"privacy":{"type":"string","example":"https://stripe.com/privacy"},"terms":{"type":"string","example":"https://stripe.com/legal"},"docs":{"type":"string","example":"https://docs.stripe.com"}}},"WebBrandDataDto":{"type":"object","properties":{"domain":{"type":"string","example":"stripe.com","description":"The canonical domain for this company."},"queriedDomain":{"type":"string","example":"stripe.co.uk","description":"Only when you asked for a different domain that resolved here."},"aliases":{"description":"Only when this brand is known by more than its canonical domain.","type":"array","items":{"type":"string"}},"name":{"type":"object","nullable":true,"example":"Stripe"},"description":{"type":"object","nullable":true,"example":"Stripe powers online and in-person payment processing and financial solutions for businesses of all sizes."},"tagline":{"type":"object","nullable":true,"example":"Financial infrastructure to grow your revenue."},"naics":{"description":"Industry, as a real NAICS code rather than a phrase nobody can group on.","allOf":[{"$ref":"#/components/schemas/BrandNaicsDto"}]},"assets":{"type":"array","items":{"$ref":"#/components/schemas/BrandAssetDto"}},"colors":{"type":"array","items":{"$ref":"#/components/schemas/BrandColorDto"}},"fonts":{"type":"array","items":{"$ref":"#/components/schemas/BrandFontDto"}},"socials":{"type":"array","items":{"$ref":"#/components/schemas/BrandSocialDto"}},"links":{"$ref":"#/components/schemas/BrandLinksDto"},"email":{"type":"string","example":"support@stripe.com"},"legalName":{"type":"string","example":"Stripe, Inc."},"sources":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/BrandFieldProvenanceDto"},"description":"Per-field provenance, keyed by field name. Lets you tell \"their markup says this\" from \"a model guessed this\"."},"resolvedAt":{"type":"object","nullable":true,"example":"2026-08-22T10:14:03.000Z"}},"required":["domain","name","description","tagline","assets","colors","fonts","socials","links","sources","resolvedAt"]},"BrandResponseDto":{"type":"object","properties":{"data":{"nullable":true,"description":"Null when the domain could not be resolved at all. Unresolved domains are free.","type":"object","allOf":[{"$ref":"#/components/schemas/WebBrandDataDto"}]}},"required":["data"]},"LogoDescriptionDto":{"type":"object","properties":{"domain":{"type":"string","example":"stripe.com"},"url":{"type":"string","example":"https://media.hydrafetch.com/brand/fe/fe927b2695157fca9fb3.webp","description":"Public and immutable, so it can be embedded anywhere."},"kind":{"type":"string","example":"symbol"},"variant":{"type":"string","enum":["light","dark","mono"],"example":"light"},"format":{"type":"string","example":"webp"},"width":{"type":"object","nullable":true,"example":180},"height":{"type":"object","nullable":true,"example":180},"dominantColor":{"type":"object","nullable":true,"example":"#543cfc"},"blurhash":{"type":"object","nullable":true,"example":"LmGk_aoh4sWHohWEWDt506WD?Sod"}},"required":["domain","url","kind","variant","format","width","height","dominantColor","blurhash"]},"BrandLogoResponseDto":{"type":"object","properties":{"data":{"nullable":true,"description":"Null when we hold no mark for the domain. A domain with no logo is free.","type":"object","allOf":[{"$ref":"#/components/schemas/LogoDescriptionDto"}]}},"required":["data"]},"BrandSearchResultDto":{"type":"object","properties":{"domain":{"type":"string","example":"stripe.com"},"name":{"type":"object","nullable":true,"example":"Stripe"},"logo":{"type":"string","example":"https://media.hydrafetch.com/brand/a0/a07c2695173dde0a1ffa.svg","description":"The primary logo, so a picker can render a recognisable row."},"color":{"type":"string","example":"#533afd","description":"The brand's primary colour."}},"required":["domain","name"]},"WebBrandSearchDataDto":{"type":"object","properties":{"query":{"type":"string","example":"stripe"},"results":{"description":"Best match first.","type":"array","items":{"$ref":"#/components/schemas/BrandSearchResultDto"}}},"required":["query","results"]},"BrandSearchResponseDto":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebBrandSearchDataDto"}},"required":["data"]},"BrandBatchDto":{"type":"object","properties":{"domains":{"example":["stripe.com","linear.app"],"type":"array","items":{"type":"string"}}}},"BrandBatchResponseDto":{"type":"object","properties":{"data":{"nullable":true,"description":"One entry per requested domain, in the order you sent them. Null where unresolved.","type":"array","items":{"$ref":"#/components/schemas/WebBrandDataDto"}}},"required":["data"]},"StyleguideWebfontDto":{"type":"object","properties":{"type":{"type":"string","enum":["google","custom"],"example":"custom"},"files":{"type":"object","additionalProperties":{"type":"string"},"description":"Weight to file URL. These point at the site's own CDN — we neither rehost nor relicense."}},"required":["type","files"]},"StyleguideColorDto":{"type":"object","properties":{"hex":{"type":"string","example":"#533afd"},"name":{"type":"string","example":"Indigo"},"role":{"type":"string","enum":["background","surface","text","accent"],"example":"accent","description":"Roles rather than a ranked list, so a colour drops straight into a theme instead of leaving you to guess which one is safe behind text."}},"required":["hex","role"]},"StyleguideFontDto":{"type":"object","properties":{"role":{"type":"string","enum":["h1","h2","h3","h4","body","link"],"example":"body"},"family":{"type":"string","example":"sohne-var"},"size":{"type":"number","example":16,"description":"Computed size in pixels."},"weight":{"type":"object","nullable":true,"example":"400"},"lineHeight":{"type":"number","example":24},"letterSpacing":{"type":"string","example":"normal"},"fallbacks":{"description":"The rest of the declared stack, for rendering before the webfont arrives.","type":"array","items":{"type":"string"}}},"required":["role","family"]},"StyleguideFontUsageDto":{"type":"object","properties":{"family":{"type":"string","example":"sohne-var"},"words":{"type":"number","example":1840},"percentWords":{"type":"number","example":92.4}},"required":["family","words","percentWords"]},"StyleguideRadiusDto":{"type":"object","properties":{"default":{"type":"string","example":"6px"},"card":{"type":"string","example":"6px"},"button":{"type":"string","example":"4px"}}},"StyleguideButtonBorderDto":{"type":"object","properties":{"width":{"type":"number","example":1},"style":{"type":"string","example":"solid"},"color":{"type":"object","nullable":true,"example":"#533afd"}},"required":["width","style","color"]},"StyleguideButtonDto":{"type":"object","properties":{"background":{"type":"string","example":"#533afd"},"color":{"type":"object","nullable":true,"example":"#ffffff"},"radius":{"type":"string","example":"4px"},"paddingX":{"type":"number","example":24},"paddingY":{"type":"number","example":15.5},"fontWeight":{"type":"object","nullable":true,"example":"400"},"fontSize":{"type":"number","example":16},"minWidth":{"type":"number","example":210,"description":"The rendered box. A button centring its label with flex has no padding to report."},"minHeight":{"type":"number","example":48},"border":{"$ref":"#/components/schemas/StyleguideButtonBorderDto"},"shadow":{"type":"string","example":"rgba(23, 23, 23, 0.08) 0px 15px 35px 0px"}},"required":["background","radius"]},"StyleguideContrastDto":{"type":"object","properties":{"textOnBackground":{"type":"number","example":21,"description":"Contrast ratio of text against background."},"meetsAA":{"type":"boolean","example":true,"description":"Whether that ratio clears WCAG AA."},"accentOnBackground":{"type":"number","example":6.19}}},"WebStyleguideDataDto":{"type":"object","properties":{"domain":{"type":"string","example":"stripe.com"},"mode":{"type":"string","enum":["light","dark"],"example":"light"},"colors":{"type":"array","items":{"$ref":"#/components/schemas/StyleguideColorDto"}},"typography":{"type":"array","items":{"$ref":"#/components/schemas/StyleguideFontDto"}},"webfonts":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/StyleguideWebfontDto"},"description":"Keyed by family name."},"fontUsage":{"type":"array","items":{"$ref":"#/components/schemas/StyleguideFontUsageDto"}},"radius":{"$ref":"#/components/schemas/StyleguideRadiusDto"},"shadows":{"type":"object","additionalProperties":{"type":"string"},"description":"Keyed by size, for example `sm`, `md`, `lg`."},"spacing":{"type":"object","additionalProperties":{"type":"string"},"description":"Keyed by step, for example `xs` through `xl`."},"button":{"$ref":"#/components/schemas/StyleguideButtonDto"},"contrast":{"description":"Whether you can put text on what we handed you.","allOf":[{"$ref":"#/components/schemas/StyleguideContrastDto"}]},"resolvedAt":{"type":"object","nullable":true,"example":"2026-08-22T10:14:03.000Z"}},"required":["domain","colors","typography","resolvedAt"]},"StyleguideResponseDto":{"type":"object","properties":{"data":{"nullable":true,"description":"Null when the domain could not be rendered. An unresolved domain is free.","type":"object","allOf":[{"$ref":"#/components/schemas/WebStyleguideDataDto"}]}},"required":["data"]},"ImagesRequestDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com","description":"The URL to harvest images from. Must be http(s)."},"maxAge":{"type":"number","minimum":0,"maximum":604800000,"description":"Serve from cache if a capture of this URL is younger than this many milliseconds. Omit for the default window; 0 always fetches fresh. Capped at 7 days."}},"required":["url"]},"WebImageDto":{"type":"object","properties":{"src":{"type":"string","example":"https://example.com/logo.png","description":"The image URL, resolved to absolute."},"alt":{"type":"object","nullable":true,"example":"Company logo","description":"The image alt text, if any."},"width":{"type":"object","nullable":true,"example":320,"description":"The image width in pixels, if declared."},"height":{"type":"object","nullable":true,"example":240,"description":"The image height in pixels, if declared."}},"required":["src","alt","width","height"]},"WebImagesDataDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com","description":"The URL you requested."},"finalUrl":{"type":"string","example":"https://example.com/","description":"The final URL after any redirects."},"images":{"description":"Every image found on the page, with its metadata.","type":"array","items":{"$ref":"#/components/schemas/WebImageDto"}}},"required":["url","finalUrl","images"]},"ImagesResponseDto":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebImagesDataDto"}},"required":["data"]},"ScreenshotRequestDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com","description":"The URL to screenshot. Must be http(s)."},"fullPage":{"type":"boolean","example":true,"description":"Capture the entire scrollable page instead of just the viewport. Default off."},"waitFor":{"type":"number","minimum":0,"maximum":30000,"description":"Extra milliseconds to let the page settle before capture."},"timeout":{"type":"number","minimum":1000,"maximum":120000,"description":"Overall time budget for the request, in milliseconds."},"maxAge":{"type":"number","minimum":0,"description":"Reuse a stored screenshot if it is younger than this many milliseconds. Defaults to 7 days, so a repeated request returns the stored PNG with `cached: true` without re-rendering — which also means it returns immediately and does not apply `waitFor`. Pass 0 to force a fresh capture."},"viewport":{"type":"string","enum":["desktop","laptop","tablet","mobile"],"example":"desktop","description":"Screen size to render at. Defaults to desktop (1920x1080). Ignored when width/height are given explicitly."},"viewportWidth":{"type":"number","minimum":320,"maximum":3840,"description":"Exact viewport width in pixels. Overrides `viewport`."},"viewportHeight":{"type":"number","minimum":240,"maximum":2160,"description":"Exact viewport height in pixels. Overrides `viewport`. With fullPage the capture still extends to the full page height."}},"required":["url"]},"WebScreenshotDataDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com","description":"The URL you requested."},"finalUrl":{"type":"string","example":"https://example.com/","description":"The final URL after any redirects."},"status":{"type":"number","example":200,"description":"HTTP status of the captured page."},"screenshot":{"type":"string","example":"https://media.hydrafetch.com/screenshots/a1/a1b2c3.png","description":"Public URL of the captured PNG. Stable for the same URL and options."},"screenshotType":{"type":"string","enum":["fullPage","viewport"],"example":"viewport","description":"Whether the capture covers the whole scrollable page or just the viewport."},"width":{"type":"number","example":1920,"description":"Image width in pixels."},"height":{"type":"number","example":1080,"description":"Image height in pixels."},"cached":{"type":"boolean","example":false,"description":"True when a stored screenshot was reused instead of capturing a new one."}},"required":["url","finalUrl","status","screenshot","screenshotType","width","height","cached"]},"ScreenshotResponseDto":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebScreenshotDataDto"}},"required":["data"]},"MapRequestDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com","description":"The site whose URLs you want to enumerate. Must be http(s)."},"includeLinks":{"type":"boolean","example":true,"description":"Also include same-site links found on the starting page, not just the site's page list."},"limit":{"type":"number","minimum":1,"maximum":5000,"example":1000,"description":"Maximum number of URLs to return."},"search":{"type":"string","maxLength":200,"example":"pricing","description":"Keep only discovered URLs containing this term."},"sitemap":{"type":"string","enum":["skip","include","only"],"example":"include","description":"Whether to use the site's published page list: skip it, include it alongside discovered links, or use it only."},"sitemapInclude":{"type":"string","maxLength":200,"example":"post","description":"On sitemap-index sites, only descend into sub-sitemaps whose URL contains one of these comma-separated terms (case-insensitive). E.g. \"post\" to target article sitemaps."},"sitemapExclude":{"type":"string","maxLength":200,"example":"tag,category,author","description":"Skip sub-sitemaps whose URL contains any of these comma-separated terms (case-insensitive). Compose with sitemapInclude — e.g. include \"post\" + exclude \"tag,category,author\" avoids WordPress taxonomy sitemaps (post_tag-sitemap, …-taxonomies-post_tag-*) that also contain \"post\"."},"order":{"type":"string","enum":["newest","oldest","sitemap"],"default":"newest","description":"Sort order by sitemap lastmod. \"newest\" (default) returns the most recent URLs first — the wanted end of a large archive under the limit. URLs without a lastmod sort last."},"before":{"type":"string","example":"2024-06-01T00:00:00Z","description":"Cursor for paging a large archive newest→oldest: return only URLs with lastmod at or before this ISO timestamp. Page by passing the oldest lastmod from the previous page; dedupe by url across pages."},"offset":{"type":"number","minimum":0,"maximum":100000,"example":5000,"description":"Skip the first N results (in the sorted order) then return the next `limit`. Pagination for sources with no lastmod (WordPress-core), where the date cursor can't apply. Page sequentially (0, limit, 2·limit, …) so the sub-sitemap cache keeps deep pages fast."},"includeSubdomains":{"type":"boolean","example":false,"description":"Also include URLs on subdomains of the site. Default off."},"ignoreQueryParameters":{"type":"boolean","example":false,"description":"Treat URLs that differ only by query string as one. Default off."}},"required":["url"]},"MapUrlEntryDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com/blog/hello"},"lastmod":{"type":"object","nullable":true,"example":"2026-05-01T12:00:00Z","description":"The <lastmod> from the sitemap, if present. null for links found on the page."}},"required":["url","lastmod"]},"MapResultDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com","description":"The site you requested."},"links":{"description":"The site's discovered URLs, each with its sitemap lastmod (null when unknown).","type":"array","items":{"$ref":"#/components/schemas/MapUrlEntryDto"}},"count":{"type":"number","example":2,"description":"How many URLs were returned."},"total":{"type":"number","example":9051,"description":"Total URLs in the enumeration this page is a slice of. Page with `offset` until offset+count reaches this — do not infer the end from a short page."},"truncated":{"type":"boolean","example":false,"description":"Whether enumeration hit its ceiling or time budget. When true, `total` is a floor rather than the real size of the site."}},"required":["url","links","count","total","truncated"]},"MapResponseDto":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MapResultDto"}},"required":["data"]},"WebhookDto":{"type":"object","properties":{"url":{"type":"string","example":"https://your-app.com/hooks/hydrafetch","description":"The URL to POST events to. Must be a public http(s) URL — private, loopback, and link-local addresses are rejected."},"events":{"type":"array","example":["page","completed"],"description":"Which events to receive. `page` fires as each page finishes; `completed` fires once when the job ends. Defaults to both.","items":{"type":"string","enum":["page","completed"]}},"headers":{"type":"object","additionalProperties":{"type":"string"},"example":{"Authorization":"Bearer your-token"},"description":"Extra headers to send with each callback, e.g. for authentication."},"secret":{"type":"string","example":"whsec_a_long_random_string","minLength":16,"maxLength":256,"description":"A shared secret. When set, each callback carries an X-Hydrafetch-Signature header you can verify to prove the request came from us and is not a replay."}},"required":["url"]},"OptLocationDto":{"type":"object","properties":{"country":{"type":"string","example":"us","description":"ISO 3166 alpha-2 country to fetch as if from."},"languages":{"example":["en-US","en"],"description":"Preferred content languages, most-preferred first.","type":"array","items":{"type":"string"}}}},"ScrapeOptionsDto":{"type":"object","properties":{"formats":{"type":"array","example":["markdown"],"description":"What to return per page. Omit for Markdown only.","items":{"type":"string","enum":["markdown","html","rawHtml","links","structured"]}},"onlyMainContent":{"type":"boolean","description":"Return only the main content, dropping boilerplate. Default true."},"includeTags":{"maxItems":50,"description":"CSS selectors to keep.","type":"array","items":{"type":"string"}},"excludeTags":{"maxItems":50,"description":"CSS selectors to strip before extraction.","type":"array","items":{"type":"string"}},"removeBase64Images":{"type":"boolean","description":"Strip inline base64 images. Default true."},"blockAds":{"type":"boolean","description":"Remove common ad and tracking elements. Default true."},"includeLinks":{"type":"boolean","description":"Keep inline links in the markdown. Default true — a bare `Read the guide` is worth less to a model than one it can follow. Turn off for the densest possible prose."},"waitFor":{"type":"number","minimum":0,"maximum":30000,"description":"Extra milliseconds to let the page settle before capture."},"timeout":{"type":"number","minimum":1000,"maximum":120000,"description":"Per-page time budget, in milliseconds."},"location":{"$ref":"#/components/schemas/OptLocationDto"},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra request headers to send when fetching each page."},"preferStructure":{"type":"boolean","description":"Preserve document structure over prose density. Default off."},"maxAge":{"type":"number","minimum":0,"maximum":604800000,"description":"Serve a page from cache if younger than this many milliseconds."}}},"CrawlRequestDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com","description":"The site to start from. Must be http(s)."},"limit":{"type":"number","minimum":1,"maximum":5000,"example":100,"description":"Maximum number of pages to scrape."},"maxDepth":{"type":"number","minimum":0,"maximum":10,"example":2,"description":"How many links deep from the starting page to follow."},"includePaths":{"maxItems":50,"example":["^/blog/.*"],"description":"Only follow URLs whose path matches every one of these patterns.","type":"array","items":{"type":"string"}},"excludePaths":{"maxItems":50,"example":["^/tag/.*"],"description":"Skip URLs whose path matches any of these patterns.","type":"array","items":{"type":"string"}},"allowSubdomains":{"type":"boolean","example":false,"description":"Also follow links into subdomains of the starting site. Default off."},"allowExternalLinks":{"type":"boolean","example":false,"description":"Also follow links that lead off the starting site. Default off."},"ignoreQueryParameters":{"type":"boolean","example":false,"description":"Treat URLs that differ only by query string as the same page. Default off."},"sitemap":{"type":"string","enum":["skip","include"],"example":"include","description":"Whether to seed discovery from the site's published page list. Default includes it."},"webhook":{"description":"Register a callback to be notified as the crawl progresses instead of polling.","allOf":[{"$ref":"#/components/schemas/WebhookDto"}]},"scrapeOptions":{"description":"How to scrape each page. Same options as a single scrape.","allOf":[{"$ref":"#/components/schemas/ScrapeOptionsDto"}]}},"required":["url"]},"CrawlAcceptedDto":{"type":"object","properties":{"crawlId":{"type":"string","example":"019f3c09-6fae-740f-9257-10c2b6af7f43","description":"Poll this crawl id for progress and results."},"status":{"type":"string","enum":["queued"],"example":"queued","description":"The job has been accepted."}},"required":["crawlId","status"]},"BatchRequestDto":{"type":"object","properties":{"urls":{"minItems":1,"maxItems":1000,"example":["https://example.com/a","https://example.com/b"],"description":"The explicit list of URLs to scrape. Each must be http(s).","type":"array","items":{"type":"string"}},"webhook":{"description":"Register a callback to be notified as the batch progresses instead of polling.","allOf":[{"$ref":"#/components/schemas/WebhookDto"}]},"scrapeOptions":{"description":"How to scrape each URL. Same options as a single scrape.","allOf":[{"$ref":"#/components/schemas/ScrapeOptionsDto"}]}},"required":["urls"]},"BatchAcceptedDto":{"type":"object","properties":{"batchId":{"type":"string","example":"019f3c09-6fae-740f-9257-10c2b6af7f43","description":"Poll this batch id for progress and results."},"status":{"type":"string","enum":["queued"],"example":"queued","description":"The job has been accepted."}},"required":["batchId","status"]},"CrawlPageResultDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com/blog/post","description":"The page URL."},"requestedUrl":{"type":"string","example":"https://example.com/blog/post/","description":"For a batch, the URL exactly as you sent it, present only when it differed from `url` after normalisation (a trailing slash or #fragment). A batch always returns one entry per URL you submitted, in order, including duplicates — so you can match results back to your input list positionally."},"status":{"type":"string","enum":["queued","running","completed","failed"],"example":"completed","description":"State of this page."},"depth":{"type":"number","example":1,"description":"How many links deep this page was from the start."},"error":{"type":"object","nullable":true,"description":"Human-readable failure message. Set when this page failed."},"errorCode":{"type":"object","nullable":true,"example":"TOO_MANY_REQUESTS","description":"Stable machine-readable failure code. Set when this page failed."},"retryable":{"type":"object","nullable":true,"example":false,"description":"When failed: true if it gave up after real retries (transient — safe to re-submit), false if a terminal failure."},"data":{"nullable":true,"description":"The scraped page, once completed.","type":"object","allOf":[{"$ref":"#/components/schemas/WebScrapeDataDto"}]}},"required":["url","status","depth","error","errorCode","retryable","data"]},"CrawlStatusResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"019f3c09-6fae-740f-9257-10c2b6af7f43","description":"The crawl or batch id."},"kind":{"type":"string","enum":["crawl","batch"],"example":"crawl","description":"Which kind of job this is."},"status":{"type":"string","enum":["running","completed","failed","cancelled"],"example":"running","description":"Overall job state."},"seedUrl":{"type":"object","nullable":true,"example":"https://example.com","description":"The starting URL, for a crawl."},"total":{"type":"number","example":100,"description":"Total pages in this job."},"completed":{"type":"number","example":42,"description":"Pages scraped so far."},"failed":{"type":"number","example":1,"description":"Pages that failed."},"creditsUsed":{"type":"number","example":42,"description":"Credits consumed so far. One per scraped page."},"pages":{"description":"Per-page status and results.","type":"array","items":{"$ref":"#/components/schemas/CrawlPageResultDto"}}},"required":["id","kind","status","seedUrl","total","completed","failed","creditsUsed","pages"]},"CrawlStatusEnvelopeDto":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CrawlStatusResponseDto"}},"required":["data"]},"WebhookDeliveryDto":{"type":"object","properties":{"id":{"type":"string","example":"019f3c09-6fae-740f-9257-10c2b6af7f43"},"event":{"type":"string","example":"crawl.completed","description":"The event this delivery carried."},"status":{"type":"string","enum":["pending","success","failed"],"example":"success","description":"pending while retries remain, success once delivered, failed once given up."},"attempts":{"type":"number","example":2,"description":"How many delivery attempts have been made."},"responseStatus":{"type":"object","nullable":true,"example":200,"description":"HTTP status your endpoint returned on the last attempt."},"error":{"type":"object","nullable":true,"example":"connect ETIMEDOUT","description":"Why the last attempt failed, if it did."},"deliveredAt":{"type":"object","nullable":true,"description":"When the delivery succeeded (ISO 8601)."},"createdAt":{"type":"string","description":"When the delivery was first created (ISO 8601)."}},"required":["id","event","status","attempts","responseStatus","error","deliveredAt","createdAt"]},"WebhookDeliveriesResponseDto":{"type":"object","properties":{"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryDto"}}},"required":["deliveries"]},"SearchRequestDto":{"type":"object","properties":{"query":{"type":"string","maxLength":500,"example":"best open source vector databases","description":"What to search the web for."},"limit":{"type":"number","minimum":1,"maximum":15,"example":5,"description":"How many ranked results to return. Omit for the default."},"scrapeResults":{"type":"boolean","example":false,"description":"When true, each result also comes back with its page fetched and returned as clean data, at 1 additional credit per page scraped. Defaults to false, which returns just the ranked title, url and snippet for the flat search credit."},"scrapeOptions":{"$ref":"#/components/schemas/ScrapeOptionsDto"},"timeRange":{"type":"string","enum":["day","week","month","year"],"example":"week","description":"Restrict results to a recency window relative to now."},"country":{"type":"string","example":"us","description":"ISO 3166 alpha-2 country code to bias results toward a region."},"includeDomains":{"maxItems":15,"example":["github.com","arxiv.org"],"description":"Only return results from these domains.","type":"array","items":{"type":"string"}},"excludeDomains":{"maxItems":15,"example":["pinterest.com"],"description":"Drop results from these domains.","type":"array","items":{"type":"string"}}},"required":["query"]},"SearchResultItemDto":{"type":"object","properties":{"title":{"type":"string","example":"Best open source vector databases","description":"The result title."},"url":{"type":"string","example":"https://example.com/vector-databases","description":"The result URL."},"snippet":{"type":"string","example":"A rundown of the leading open source vector databases and how they compare.","description":"A short snippet describing the result."},"rank":{"type":"number","example":1,"description":"The result's position in the ranked list."},"data":{"nullable":true,"description":"The scraped page for this result, or null when scraping is off or unavailable.","type":"object","allOf":[{"$ref":"#/components/schemas/WebScrapeDataDto"}]}},"required":["title","url","snippet","rank","data"]},"SearchResultDto":{"type":"object","properties":{"query":{"type":"string","example":"best open source vector databases","description":"The query you searched."},"status":{"type":"string","enum":["ok","no_results"],"example":"ok","description":"Whether the engine found anything: `ok` when it returned results, `no_results` when it answered but the web had no match. An empty `results` with `no_results` is a real miss — if no engine could answer at all, the request fails with 503 rather than returning an empty list."},"results":{"description":"The ranked results.","type":"array","items":{"$ref":"#/components/schemas/SearchResultItemDto"}}},"required":["query","status","results"]},"SearchResponseDto":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SearchResultDto"}},"required":["data"]},"ExtractRequestDto":{"type":"object","properties":{"urls":{"maxItems":10,"example":["https://example.com/products/widget","https://example.com/products/*"],"description":"The pages to extract from. Each must be an http(s) URL. A trailing `/*` marks a crawl scope: every page discovered under that path is extracted and merged into the result.","type":"array","items":{"type":"string"}},"schema":{"type":"object","additionalProperties":true,"description":"JSON Schema describing the shape you want back. Optional if `prompt` is given; when both are present the schema fixes the field names and types while the prompt guides what to pull."},"prompt":{"type":"string","maxLength":2000,"example":"Pull the product name, price in USD, and whether it is in stock.","description":"Natural-language instruction for what to extract. Use with or instead of a schema."},"preferStructure":{"type":"boolean","description":"Preserve document structure (headings, lists, tables) over prose density when reading the page — good for listing and catalog pages. Default off."},"enableWebSearch":{"type":"boolean","description":"Pull in extra source pages by web-searching your prompt, to fill fields your URLs do not cover. Requires a `prompt`."},"showSources":{"type":"boolean","description":"Return the concrete list of URLs that were actually extracted, after any wildcard and web-search expansion. Default off."},"showConfidence":{"type":"boolean","description":"For each field, return a confidence score and the exact source passage the value was drawn from. Default off."},"mergeEntities":{"type":"boolean","description":"Merge the per-page results into one deduplicated collection — one row per entity, with its contributing source URLs — instead of a separate result per page. Default off."},"maxAge":{"type":"number","minimum":0,"maximum":604800000,"description":"Reuse a recent capture of each page if it is younger than this many milliseconds. Omit or 0 to always fetch fresh. Capped at 7 days."}},"required":["urls"]},"FieldProvenanceDto":{"type":"object","properties":{"confidence":{"type":"number","minimum":0,"maximum":1,"example":0.92,"description":"How certain the value is correct given the page, from 0 to 1."},"evidence":{"type":"string","example":"Priced at $49.00 with free shipping.","description":"The exact short passage the value was drawn from, or an empty string if none."}},"required":["confidence","evidence"]},"ExtractItemResultDto":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com/products/widget","description":"The page this result came from."},"data":{"type":"object","additionalProperties":true,"nullable":true,"description":"The extracted data, shaped by your schema and/or prompt. Null when nothing matched."},"fields":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/FieldProvenanceDto"},"description":"Per-field confidence and source passage, keyed by field name. Present only when `showConfidence` is set."},"error":{"type":"object","nullable":true,"example":null,"description":"Set when this page could not be extracted; null on success."}},"required":["url","data","error"]},"MergedEntityDto":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true,"description":"The unioned data for one entity, filled across every contributing page."},"sources":{"description":"Every source URL that contributed to this entity.","type":"array","items":{"type":"string"}}},"required":["data","sources"]},"ExtractResultDto":{"type":"object","properties":{"results":{"description":"One result per extracted page.","type":"array","items":{"$ref":"#/components/schemas/ExtractItemResultDto"}},"sources":{"description":"The concrete URLs actually extracted, after wildcard and web-search expansion. Present only when `showSources` is set.","type":"array","items":{"type":"string"}},"collection":{"description":"The deduplicated collection, one row per entity. Present only when `mergeEntities` is set.","type":"array","items":{"$ref":"#/components/schemas/MergedEntityDto"}}},"required":["results"]},"ExtractResponseDto":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ExtractResultDto"}},"required":["data"]},"WebErrorBody":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["VALIDATION_ERROR","INVALID_INPUT","UNAUTHORIZED","INSUFFICIENT_CREDITS","FORBIDDEN","WORKSPACE_BANNED","NOT_FOUND","TOO_MANY_REQUESTS","SERVICE_UNAVAILABLE","INTERNAL_SERVER_ERROR"],"description":"Stable, machine-readable reason. Branch on this rather than on the message, which may be reworded.","example":"INSUFFICIENT_CREDITS"},"message":{"type":"string","description":"Human-readable explanation. Safe to show a user, not to parse.","example":"Insufficient credits"},"details":{"type":"object","additionalProperties":true,"description":"Optional machine-readable context, present on validation failures."}}},"WebErrorMeta":{"type":"object","properties":{"requestId":{"type":"string","description":"Quote this when contacting support about a specific failure.","example":"019e8a3c-9f0b-7c12-88ab-1d2e3f4a5b6c"}}},"WebError":{"type":"object","required":["success","error","meta"],"description":"Every failure on this API returns this shape, whatever the status. Successful responses never carry it.","properties":{"success":{"type":"boolean","enum":[false],"example":false},"error":{"$ref":"#/components/schemas/WebErrorBody"},"meta":{"$ref":"#/components/schemas/WebErrorMeta"}}}}},"security":[{"apiKey":[]}]}