{"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"}}}}},"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"}}}}},"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"}}}}},"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"}}}}},"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"}}}}},"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"}}}}},"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"}}}}},"summary":"Get scrape job status","tags":["Scrape"]}},"/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"}}}}},"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"}}}}},"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"}}}}},"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"}}}}},"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"}}}}},"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"}}}}},"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"}}}}},"summary":"List webhook deliveries for a batch","tags":["Crawl & batch"]}},"/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."}},"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":""}},"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."}},"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."}},"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."}},"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"}}}}},"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"}}}}},"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."}},"summary":"Serve a company logo","tags":["Logo"]}},"/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"}}}}},"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"}}}}},"summary":"Extract structured data from URLs","tags":["Extract"]}}},"info":{"title":"Hydrafetch API","description":"Hydrafetch is a web data API for LLMs 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. Errors return a structured body with a stable `code` and an HTTP status.","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"]},"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"]},"BrandBatchDto":{"type":"object","properties":{"domains":{"example":["stripe.com","linear.app"],"type":"array","items":{"type":"string"}}}},"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"]},"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"]}}},"security":[{"apiKey":[]}]}