{"openapi":"3.1.0","info":{"title":"Agent Fetch Hub","version":"1.0.0","description":"Pay-per-call web extraction for autonomous agents. No signup, no API key, no dashboard. Every call is settled in USDC over the x402 protocol.","contact":{"name":"Die Netzhandwerker","url":"https://netzhandwerker.de"}},"servers":[{"url":"https://fetch.halowerk.com"}],"paths":{"/extract":{"post":{"summary":"Fetch one URL and return clean article Markdown without navigation, ads or cookie banners.","description":"Readability extraction with boilerplate removal. Returns title, byline, language, word count and Markdown body. Optional plain text or cleaned HTML. Price: 0.001 USDC per call, settled over x402 on Base Mainnet.","operationId":"extract_url","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Absolute http or https URL to extract."},"format":{"type":"string","enum":["markdown","text","html"],"default":"markdown"},"include_links":{"type":"boolean","default":false,"description":"Return outbound links found in the document."},"include_images":{"type":"boolean","default":false},"max_chars":{"type":"integer","minimum":500,"maximum":400000,"default":200000}}}}}},"responses":{"200":{"description":"Extraction result","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid URL or request body. Not charged."},"402":{"description":"Payment required. Retry with a PAYMENT-SIGNATURE header."},"403":{"description":"Origin robots.txt disallows the path, or the origin refused access. Not charged."},"415":{"description":"Unsupported content type. Not charged."},"429":{"description":"Too many unsettled requests from this address. Not charged."},"502":{"description":"Origin unreachable. Not charged."}},"x-x402":{"price":{"amount":"1000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","network":"eip155:8453","display":"$0.001"}}}},"/metadata":{"post":{"summary":"Return title, description, OpenGraph card, canonical URL, feeds, favicon and detected technologies for one URL.","description":"Head-only metadata pass. Cheaper than a full extraction when an agent only needs to label or deduplicate a link. Price: 0.002 USDC per call, settled over x402 on Base Mainnet.","operationId":"url_metadata","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Absolute http or https URL to extract."}}}}}},"responses":{"200":{"description":"Extraction result","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid URL or request body. Not charged."},"402":{"description":"Payment required. Retry with a PAYMENT-SIGNATURE header."},"403":{"description":"Origin robots.txt disallows the path, or the origin refused access. Not charged."},"415":{"description":"Unsupported content type. Not charged."},"429":{"description":"Too many unsettled requests from this address. Not charged."},"502":{"description":"Origin unreachable. Not charged."}},"x-x402":{"price":{"amount":"2000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","network":"eip155:8453","display":"$0.002"}}}},"/structured":{"post":{"summary":"Fill a caller supplied JSON Schema from one web page and report source and confidence for every field.","description":"Reads schema.org JSON-LD, microdata and OpenGraph first and only asks a language model for what those sources left open. A value is written only when it occurs verbatim in the document or follows from it by calculation, otherwise the field stays empty and is listed under unavailable_fields. The result is validated against the submitted schema with ajv. Price: 0.005 USDC per call, settled over x402 on Base Mainnet.","operationId":"extract_structured","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","schema"],"properties":{"url":{"type":"string","format":"uri","description":"Absolute http or https URL to read."},"schema":{"type":"object","description":"Target JSON Schema, draft 2020-12. Only the types object, array, string, number, integer, boolean and null are accepted; composition keywords such as $ref, oneOf, anyOf, allOf and if/then are refused. At most 200 fields and no deeper than max_depth. The root must describe an object."},"strict":{"type":"boolean","default":true,"description":"true rejects the call with 422 when the result violates the submitted schema, so no partial data is returned and nothing is charged. false returns the partial data with the error list."},"max_depth":{"type":"integer","minimum":1,"maximum":4,"default":3,"description":"Maximum nesting depth the submitted schema may use. A deeper schema is refused before payment."}}}}}},"responses":{"200":{"description":"Extraction result","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"},"data":{"type":"object","description":"The filled schema."},"validation":{"type":"object","properties":{"valid":{"type":"boolean"},"errors":{"type":"array","items":{"type":"object"}}}},"field_sources":{"type":"object","description":"Per field path one of jsonld, microdata, dom or model. A field that is absent here carries no value.","additionalProperties":{"type":"string","enum":["jsonld","microdata","dom","model"]}},"confidence":{"type":"object","additionalProperties":{"type":"number","minimum":0,"maximum":1}},"unavailable_fields":{"type":"array","items":{"type":"string"}},"fetched_at":{"type":"string","format":"date-time"},"cached":{"type":"boolean"},"charged":{"type":"boolean"}}}}}},"400":{"description":"Invalid URL, invalid request body, or a schema that is too large, too deep or uses unsupported keywords. Checked before payment, so never charged."},"402":{"description":"Payment required. Retry with a PAYMENT-SIGNATURE header."},"403":{"description":"Origin robots.txt disallows the path, or the origin refused access. Not charged."},"415":{"description":"Unsupported content type. Not charged."},"422":{"description":"strict=true and the extracted data violates the submitted schema. No partial data, not charged."},"429":{"description":"Too many unsettled requests from this address. Not charged."},"502":{"description":"Origin unreachable. Not charged."}},"x-x402":{"price":{"amount":"5000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","network":"eip155:8453","display":"$0.005"}}}},"/diff":{"post":{"summary":"Compare a page against its last stored state, or two supplied documents, and report only the content changes.","description":"Noise is removed on both sides before comparing: timestamps, counters, session and CSRF values, ads, cookie notices, navigation, footers, shuffled ordering, cache busting parameters and rotating image filenames. What remains is reported as text, price, link, meta, structured, form, removed or added changes. A first call for an unknown URL stores the baseline and costs 0.001 USDC. Price: 0.003 USDC per call, 0.001 USDC when the call only stores a baseline, settled over x402 on Base Mainnet.","operationId":"page_diff","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Either \"url\" (compare against the state fetchwerk stored for it) or \"before\" and \"after\" (compare two supplied documents).","properties":{"url":{"type":"string","format":"uri","description":"Page to fetch and compare against its last stored state."},"since":{"type":"string","format":"date-time","description":"ISO timestamp. Picks the stored state at or before this moment instead of the newest one."},"before":{"type":"string","description":"Earlier document as HTML or Markdown. No network access is used."},"after":{"type":"string","description":"Later document as HTML or Markdown."},"before_fetched_at":{"type":"string","format":"date-time","description":"Optional, echoed back for inline comparisons."},"after_fetched_at":{"type":"string","format":"date-time","description":"Optional, echoed back for inline comparisons."}},"anyOf":[{"required":["url"]},{"required":["before","after"]}]}}}},"responses":{"200":{"description":"Extraction result","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid URL or request body. Not charged."},"402":{"description":"Payment required. Retry with a PAYMENT-SIGNATURE header."},"403":{"description":"Origin robots.txt disallows the path, or the origin refused access. Not charged."},"415":{"description":"Unsupported content type. Not charged."},"429":{"description":"Too many unsettled requests from this address. Not charged."},"502":{"description":"Origin unreachable. Not charged."}},"x-x402":{"price":{"amount":"3000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","network":"eip155:8453","display":"$0.003"}}}},"/batch/extract":{"post":{"summary":"Extract up to ten URLs in one paid call.","description":"Same extraction as /extract, executed concurrently. Failed URLs are reported per item and never abort the batch. Price: 0.008 USDC per call, settled over x402 on Base Mainnet.","operationId":"extract_batch","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["urls"],"properties":{"urls":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string","format":"uri"}},"format":{"type":"string","enum":["markdown","text","html"],"default":"markdown"},"max_chars":{"type":"integer","minimum":500,"maximum":400000,"default":200000}}}}}},"responses":{"200":{"description":"Extraction result","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid URL or request body. Not charged."},"402":{"description":"Payment required. Retry with a PAYMENT-SIGNATURE header."},"403":{"description":"Origin robots.txt disallows the path, or the origin refused access. Not charged."},"415":{"description":"Unsupported content type. Not charged."},"429":{"description":"Too many unsettled requests from this address. Not charged."},"502":{"description":"Origin unreachable. Not charged."}},"x-x402":{"price":{"amount":"8000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","network":"eip155:8453","display":"$0.008"}}}},"/product":{"post":{"summary":"Return the structured offer of one product page: identifiers, price, availability, shipping, variants, ratings, images and seller, each with its source.","description":"Reads schema.org Product JSON-LD first, then microdata, then OpenGraph product, then DOM patterns, then visible text. Every field carries a field_evidence entry naming source, selector and raw value. Prices are parsed, never calculated or converted. A page without product markup answers is_product=false with a reason and is still charged, because that answer is the service. Price: 0.005 USDC per call, settled over x402 on Base Mainnet.","operationId":"extract_product","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Absolute http or https URL of a single product page."},"currency_hint":{"type":"string","pattern":"^[A-Za-z]{3}$","description":"ISO 4217 code such as EUR or USD. Used to disambiguate the $ and kr symbols and the decimal separator. It never triggers a conversion."},"want_variants":{"type":"boolean","default":true,"description":"Collect size, colour and other variants with their own price, availability, GTIN and URL."}}}}}},"responses":{"200":{"description":"Structured product offer with a field_evidence entry per field. Also returned with is_product=false and a reason when the URL is not a product page, which is charged because that answer is the service.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid URL or request body. Not charged."},"402":{"description":"Payment required. Retry with a PAYMENT-SIGNATURE header."},"403":{"description":"Origin robots.txt disallows the path, or the origin refused access. Not charged."},"415":{"description":"Unsupported content type. Not charged."},"429":{"description":"Too many unsettled requests from this address. Not charged."},"502":{"description":"Origin unreachable. Not charged."}},"x-x402":{"price":{"amount":"5000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","network":"eip155:8453","display":"$0.005"}}}},"/health":{"get":{"summary":"Service health, no payment required","responses":{"200":{"description":"ok"}}}},"/pricing":{"get":{"summary":"Machine readable price list, no payment required","responses":{"200":{"description":"ok"}}}}},"x-service":{"slug":"fetchwerk","tags":["web-extraction","url-to-markdown","readability","scraping","rag-ingest","agent-tools","metadata","structured-extraction","json-schema","schema-org","product-data","price-extraction","e-commerce","change-detection","page-monitoring","diff"],"payment_protocol":"x402","endpoint_count":8,"paid_endpoint_count":6}}