# Structured Data Extraction API $0.02 per call, pay only for 200 responses Extract structured JSON from a public web page for AI agents: send a URL and a JSON Schema, get back JSON that validates against that schema, with optional JavaScript rendering and premium proxies. Optional schema fields may be missing or null; only fields listed in required are guaranteed to be present in a successful response. Optional nulls are omitted before validation. Answers that are not valid JSON or do not match the schema are never charged. Product: https://fastaf.co/apis/extract-api/ x402: $0.020000 per successful call, USDC on Base. Live PAYMENT-REQUIRED is authoritative. MCP tools: extract ## Example request curl -i -X POST 'https://api.fastaf.co/x402/v1/extract' \ -H 'Content-Type: application/json' \ -d '{"url":"https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html","schema":{"type":"object","required":["title","price","in_stock"],"properties":{"title":{"type":"string"},"price":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"number"},"currency":{"type":"string"}}},"in_stock":{"type":"boolean"}}}}' ## Illustrative 402 response Recipient is a placeholder. Never pay this example; request a fresh live challenge. HTTP/1.1 402 Payment Required Content-Type: application/json PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6MiwicmVzb3VyY2UiOnsidXJsIjoiaHR0cHM6Ly9hcGkuZmFzdGFmLmNvL3g0MDIvdjEvZXh0cmFjdCIsImRlc2NyaXB0aW9uIjoiU3RydWN0dXJlZCBkYXRhIGV4dHJhY3Rpb24gKEpTT04gU2NoZW1hKSIsIm1pbWVUeXBlIjoiYXBwbGljYXRpb24vanNvbiJ9LCJhY2NlcHRzIjpbeyJzY2hlbWUiOiJleGFjdCIsIm5ldHdvcmsiOiJlaXAxNTU6ODQ1MyIsImFtb3VudCI6IjIwMDAwIiwiYXNzZXQiOiIweDgzMzU4OWZDRDZlRGI2RTA4ZjRjN0MzMkQ0ZjcxYjU0YmRBMDI5MTMiLCJwYXlUbyI6IjB4MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMSIsIm1heFRpbWVvdXRTZWNvbmRzIjozMDAsImV4dHJhIjp7Im5hbWUiOiJVU0QgQ29pbiIsInZlcnNpb24iOiIyIn19XX0= { "error": "payment_required", "x402Version": 2, "resource": { "url": "https://api.fastaf.co/x402/v1/extract", "description": "Structured data extraction (JSON Schema)", "mimeType": "application/json" }, "accepts": [ { "scheme": "exact", "network": "eip155:8453", "amount": "20000", "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "payTo": "0x1111111111111111111111111111111111111111", "maxTimeoutSeconds": 300, "extra": { "name": "USD Coin", "version": "2" } } ] } ## Success example JSON that validates against the request schema, minified. Optional schema fields may be missing or null; only fields listed in required are guaranteed to be present in a successful response. Optional nulls are omitted before validation. Answers that are not JSON, do not match the schema or exceed 64 KB return 422 extraction_failed with validation_errors and are never charged or settled. { "title": "A Light in the Attic", "price": { "amount": 51.77, "currency": "GBP" }, "in_stock": true } ## OpenAPI operations { "post": { "operationId": "x402PostExtract", "summary": "Structured data extraction (JSON Schema)", "x-tool-slug": "extract_structured_data", "description": "Extract structured JSON from a public web page for AI agents: send a URL and a JSON Schema, get back JSON that validates against that schema, with optional JavaScript rendering and premium proxies. Optional schema fields may be missing or null; only fields listed in required are guaranteed to be present in a successful response. Optional nulls are omitted before validation. Answers that are not valid JSON or do not match the schema are never charged. Provided by Structured data extraction (JSON Schema). Price: $0.020000 USDC fixed per successful call. Docs: https://fastaf.co POST only, with a JSON body {url, schema, render_js?, premium?}; a GET or an empty POST only returns the 402 quote. One fixed price for plain, rendered and premium pages, settled only when the answer is JSON that validates against schema. An invalid or oversized schema returns 402 when unsigned, or 400 before payment verification/settlement when signed. Reddit and Amazon pages are refused the same way.", "tags": [ "extraction", "structured-data", "json-schema", "web", "scrape" ], "x-category": "extraction", "x-x402-discovery": { "resource": { "url": "https://api.fastaf.co/x402/v1/extract", "description": "Extract structured JSON from a public web page for AI agents: send a URL and a JSON Schema, get back JSON that validates against that schema, with optional JavaScript rendering and premium proxies. Optional schema fields may be missing or null; only fields listed in required are guaranteed to be present in a successful response. Optional nulls are omitted before validation. Answers that are not valid JSON or do not match the schema are never charged. Provided by Structured data extraction (JSON Schema). Price: $0.020000 USDC per successful call. Docs: https://fastaf.co", "serviceName": "FastAF", "tags": [ "data", "scraping", "web-data", "api", "agents" ], "iconUrl": "https://fastaf.co/favicon.ico", "homepage": "https://fastaf.co", "website": "https://fastaf.co", "docsUrl": "https://fastaf.co/apis/extract-api/", "openApiUrl": "https://api.fastaf.co/openapi.json", "mimeType": "application/json" }, "extensions": { "bazaar": { "info": { "input": { "type": "http", "bodyType": "json", "body": { "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html", "schema": { "type": "object", "required": [ "title", "price", "in_stock" ], "properties": { "title": { "type": "string" }, "price": { "type": "object", "required": [ "amount", "currency" ], "properties": { "amount": { "type": "number" }, "currency": { "type": "string" } } }, "in_stock": { "type": "boolean" } } } }, "method": "POST" }, "output": { "type": "json", "example": { "title": "A Light in the Attic", "price": { "amount": 51.77, "currency": "GBP" }, "in_stock": true } }, "homepage": "https://fastaf.co", "website": "https://fastaf.co", "docsUrl": "https://fastaf.co/apis/extract-api/", "openApiUrl": "https://api.fastaf.co/openapi.json" }, "schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "input": { "type": "object", "properties": { "type": { "type": "string", "const": "http" }, "method": { "type": "string", "enum": [ "POST" ] }, "bodyType": { "type": "string", "enum": [ "json", "form-data", "text" ] }, "body": { "type": "object", "description": "POST only, JSON body: a public page url and a JSON Schema (draft 2020-12 subset: at most 8 KB, 5 levels and 50 properties, local $ref only, root type object or array). render_js (alias dynamic) and premium are optional; challenge_mode is not available.", "examples": [ { "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html", "schema": { "type": "object", "required": [ "title", "price", "in_stock" ], "properties": { "title": { "type": "string" }, "price": { "type": "object", "required": [ "amount", "currency" ], "properties": { "amount": { "type": "number" }, "currency": { "type": "string" } } }, "in_stock": { "type": "boolean" } } } } ], "additionalProperties": false, "properties": { "url": { "type": "string", "format": "uri", "pattern": "^https?://", "maxLength": 8192, "description": "Required public HTTP(S) page URL, at most 8192 characters. Same rules as scrape: private targets and login paths are refused, Zillow/eBay point to their endpoints, Booking is rendered; Reddit and Amazon pages are refused. Nothing is charged for a refused URL.", "examples": [ "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html" ] }, "schema": { "type": "object", "additionalProperties": true, "description": "Required JSON Schema object (draft 2020-12 subset) describing the JSON to return. Root type object or array; at most 8 KB without whitespace, 5 levels deep (root included) and 50 properties in total; local $ref (#/$defs/...) only, no recursion. Keywords: type, properties, required, additionalProperties, items, prefixItems, enum, const, anyOf, oneOf, allOf, not, $defs, format, pattern, numeric and length bounds, and annotations. An invalid schema returns 400 before anything is charged.", "examples": [ { "type": "object", "required": [ "title", "price", "in_stock" ], "properties": { "title": { "type": "string" }, "price": { "type": "object", "required": [ "amount", "currency" ], "properties": { "amount": { "type": "number" }, "currency": { "type": "string" } } }, "in_stock": { "type": "boolean" } } } ] }, "render_js": { "type": "boolean", "description": "Render JavaScript before extracting; true/false, default false (booking.com defaults true). Same price." }, "dynamic": { "type": "boolean", "description": "Alias for render_js; cannot disagree with it. Same price." }, "premium": { "type": "boolean", "description": "Use residential proxies; true/false, default false. Same price." } }, "required": [ "url", "schema" ] } }, "required": [ "type", "method", "bodyType", "body" ], "additionalProperties": false }, "output": { "type": "object", "properties": { "type": { "type": "string" }, "example": { "type": [ "object", "array" ], "description": "JSON that validates against the request schema, minified. Optional schema fields may be missing or null; only fields listed in required are guaranteed to be present in a successful response. Optional nulls are omitted before validation. Answers that are not JSON, do not match the schema or exceed 64 KB return 422 extraction_failed with validation_errors and are never charged or settled." } }, "required": [ "type" ] }, "homepage": { "type": "string", "format": "uri" }, "website": { "type": "string", "format": "uri" }, "docsUrl": { "type": "string", "format": "uri" }, "openApiUrl": { "type": "string", "format": "uri" } }, "required": [ "input" ], "title": "Structured data extraction (JSON Schema)", "description": "Extract structured JSON from a public web page for AI agents: send a URL and a JSON Schema, get back JSON that validates against that schema, with optional JavaScript rendering and premium proxies. Optional schema fields may be missing or null; only fields listed in required are guaranteed to be present in a successful response. Optional nulls are omitted before validation. Answers that are not valid JSON or do not match the schema are never charged.", "x-tool-slug": "extract_structured_data" }, "metadata": { "provider": { "name": "FastAF", "description": "FastAF: Web data for AI agents, pay per call in USDC via x402, no account: Google search, Maps, Patents, Flights, News, Shopping, Scholar, Jobs, AI Mode, Amazon, eBay, Walmart, Zillow, YouTube transcripts, public LinkedIn/X profiles, scraping and screenshots.", "homepage": "https://fastaf.co", "website": "https://fastaf.co", "docsUrl": "https://fastaf.co/apis/extract-api/", "openApiUrl": "https://api.fastaf.co/openapi.json" } }, "routeTemplate": "/x402/v1/extract" } } }, "x-output-schema": { "type": [ "object", "array" ], "description": "JSON that validates against the request schema, minified. Optional schema fields may be missing or null; only fields listed in required are guaranteed to be present in a successful response. Optional nulls are omitted before validation. Answers that are not JSON, do not match the schema or exceed 64 KB return 422 extraction_failed with validation_errors and are never charged or settled." }, "x-input-example": { "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html", "schema": { "type": "object", "required": [ "title", "price", "in_stock" ], "properties": { "title": { "type": "string" }, "price": { "type": "object", "required": [ "amount", "currency" ], "properties": { "amount": { "type": "number" }, "currency": { "type": "string" } } }, "in_stock": { "type": "boolean" } } } }, "x-output-example": { "title": "A Light in the Attic", "price": { "amount": 51.77, "currency": "GBP" }, "in_stock": true }, "security": [], "x-payment-info": { "protocols": [ { "x402": {} } ], "price": { "mode": "fixed", "currency": "USD", "amount": "0.020000" } }, "responses": { "200": { "description": "Successful result; payment settled. Content type depends on the requested format. A JSON object answer ends with request_id and receipt (see the Receipt schema: USD price paid, sha256 of the data, x402_tx); every format carries X-Request-Id and X-FastAF-Receipt.", "headers": { "PAYMENT-RESPONSE": { "description": "Base64-encoded x402 v2 settlement receipt.", "schema": { "type": "string" } }, "X-Request-Id": { "description": "Unique id of this request (req_ + 32 hex). Sent on every response, errors included; quote it to support.", "schema": { "type": "string" } }, "X-FastAF-Receipt": { "description": "See the Receipt schema.", "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "type": [ "object", "array" ], "description": "JSON that validates against the request schema, minified. Optional schema fields may be missing or null; only fields listed in required are guaranteed to be present in a successful response. Optional nulls are omitted before validation. Answers that are not JSON, do not match the schema or exceed 64 KB return 422 extraction_failed with validation_errors and are never charged or settled." }, "example": { "title": "A Light in the Attic", "price": { "amount": 51.77, "currency": "GBP" }, "in_stock": true } } } }, "400": { "description": "Invalid parameters, blocked target, or options_need_api_key on a signed request; nothing charged. Validation errors name the affected parameter and include example (also example_url) with a complete valid GET request URL and accepted_aliases.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "402": { "$ref": "#/components/responses/X402PaymentRequired" }, "404": { "description": "target_not_found: the requested resource was not found (Amazon product/offer: Product not found); nothing settled. Also x402_not_enabled when pay-per-call is disabled on this deployment.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "This signed payment is already in use or has already paid for a call. Or spend_cap_exceeded: the call would exceed X-FastAF-Max-Spend. Nothing was charged.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "description": "extraction_failed: the page could not be extracted as JSON, the JSON did not match the schema (validation_errors lists why), or it exceeded 64 KB. Never charged; on x402 never settled.", "content": { "application/json": { "schema": { "type": "object", "required": [ "error", "reason", "validation_errors" ], "properties": { "error": { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "string", "const": "extraction_failed" }, "message": { "type": "string" } } }, "reason": { "type": "string", "enum": [ "unparsable", "schema_mismatch", "too_large" ] }, "validation_errors": { "type": "array", "maxItems": 20, "description": "Schema validation errors (schema_mismatch only), as JSON pointers into the extracted data.", "items": { "type": "object", "required": [ "path", "message" ], "properties": { "path": { "type": "string", "examples": [ "#/rating" ] }, "message": { "type": "string" } } } } } } } } }, "429": { "description": "IP burst limit reached. Retry after the Retry-After header interval.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "502": { "description": "Upstream failed, or returned blocked, empty or incomplete data; nothing settled. A blocked answer (target_blocked: captcha, bot check, empty page, or HTTP 403 on scrape and serp) adds blocked: true and reason to the body and the X-FastAF-Blocked header.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }, "headers": { "X-FastAF-Blocked": { "description": "The block reason, on blocked calls only.", "schema": { "type": "string", "enum": [ "challenge", "captcha", "empty", "too_short", "incomplete", "not_data", "serp_blocked", "http_403", "http_429", "http_503" ], "description": "Why the call was flagged as blocked: challenge (bot check page), captcha (reCAPTCHA/hCaptcha widget), empty or too_short (no content), incomplete (results missing), not_data (a web page in place of JSON), serp_blocked (Google's unusual-traffic or captcha page without organic results), http_403 / http_429 / http_503 (the data source refused the call)." } } } }, "503": { "description": "Temporarily unavailable; nothing settled. Always with Retry-After. The data source timing out or being down returns {error: {code: 'upstream_timeout' | 'upstream_unavailable', message, stage: 'upstream_fetch', retry_after: 5}}; capacity or payment configuration problems keep the Error shape.", "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer", "minimum": 1 } } }, "content": { "application/json": { "schema": { "anyOf": [ { "type": "object", "additionalProperties": false, "required": [ "error" ], "properties": { "error": { "type": "object", "additionalProperties": false, "required": [ "code", "message", "stage", "retry_after" ], "properties": { "code": { "type": "string", "enum": [ "upstream_timeout", "upstream_unavailable" ] }, "message": { "type": "string" }, "stage": { "type": "string", "const": "upstream_fetch" }, "retry_after": { "type": "integer", "const": 5, "description": "Same value as the Retry-After header, in seconds." } } }, "blocked": { "type": "boolean", "const": true, "description": "Present on scrape and serp when the data source answered HTTP 503: reported as a block. Never charged." }, "reason": { "type": "string", "const": "http_503", "description": "Why the call was flagged as blocked; also sent as the X-FastAF-Blocked header." } }, "example": { "error": { "code": "upstream_timeout", "message": "The data source did not answer in time. Nothing was charged; retry after Retry-After seconds.", "stage": "upstream_fetch", "retry_after": 5 } } }, { "$ref": "#/components/schemas/Error" } ] } } } } }, "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "description": "POST only, JSON body: a public page url and a JSON Schema (draft 2020-12 subset: at most 8 KB, 5 levels and 50 properties, local $ref only, root type object or array). render_js (alias dynamic) and premium are optional; challenge_mode is not available.", "examples": [ { "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html", "schema": { "type": "object", "required": [ "title", "price", "in_stock" ], "properties": { "title": { "type": "string" }, "price": { "type": "object", "required": [ "amount", "currency" ], "properties": { "amount": { "type": "number" }, "currency": { "type": "string" } } }, "in_stock": { "type": "boolean" } } } } ], "additionalProperties": false, "properties": { "url": { "type": "string", "format": "uri", "pattern": "^https?://", "maxLength": 8192, "description": "Required public HTTP(S) page URL, at most 8192 characters. Same rules as scrape: private targets and login paths are refused, Zillow/eBay point to their endpoints, Booking is rendered; Reddit and Amazon pages are refused. Nothing is charged for a refused URL.", "examples": [ "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html" ] }, "schema": { "type": "object", "additionalProperties": true, "description": "Required JSON Schema object (draft 2020-12 subset) describing the JSON to return. Root type object or array; at most 8 KB without whitespace, 5 levels deep (root included) and 50 properties in total; local $ref (#/$defs/...) only, no recursion. Keywords: type, properties, required, additionalProperties, items, prefixItems, enum, const, anyOf, oneOf, allOf, not, $defs, format, pattern, numeric and length bounds, and annotations. An invalid schema returns 400 before anything is charged.", "examples": [ { "type": "object", "required": [ "title", "price", "in_stock" ], "properties": { "title": { "type": "string" }, "price": { "type": "object", "required": [ "amount", "currency" ], "properties": { "amount": { "type": "number" }, "currency": { "type": "string" } } }, "in_stock": { "type": "boolean" } } } ] }, "render_js": { "type": "boolean", "description": "Render JavaScript before extracting; true/false, default false (booking.com defaults true). Same price." }, "dynamic": { "type": "boolean", "description": "Alias for render_js; cannot disagree with it. Same price." }, "premium": { "type": "boolean", "description": "Use residential proxies; true/false, default false. Same price." } }, "required": [ "url", "schema" ] }, "example": { "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html", "schema": { "type": "object", "required": [ "title", "price", "in_stock" ], "properties": { "title": { "type": "string" }, "price": { "type": "object", "required": [ "amount", "currency" ], "properties": { "amount": { "type": "number" }, "currency": { "type": "string" } } }, "in_stock": { "type": "boolean" } } } } } } }, "parameters": [ { "name": "X-FastAF-Max-Spend", "in": "header", "required": false, "description": "Optional spending cap in USD, decimal with up to 6 places (e.g. 0.01). If this route's fixed price is above it, the call is refused with 409 spend_cap_exceeded before any payment challenge. x402 clients sign every payment, so no session total is kept here.", "schema": { "type": "string", "pattern": "^\\d{1,7}(?:\\.\\d{1,6})?$", "examples": [ "0.50" ] } } ] } } ## API-key operations { "post": { "tags": [ "API" ], "summary": "Structured JSON extraction from a web page", "description": "Extract structured JSON from a public web page for AI agents: send a URL and a JSON Schema, get back JSON that validates against that schema, with optional JavaScript rendering and premium proxies. Optional schema fields may be missing or null; only fields listed in required are guaranteed to be present in a successful response. Optional nulls are omitted before validation. Answers that are not valid JSON or do not match the schema are never charged. Price: 40 prepaid credits per successful call, whatever the options.", "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Provider response. A JSON object answer ends with request_id and receipt (see the Receipt schema); every format carries X-Request-Id and X-FastAF-Receipt.", "headers": { "X-FastAF-Credits-Used": { "schema": { "type": "integer" } }, "X-FastAF-Free-Credits-Used": { "description": "The part of X-FastAF-Credits-Used paid with the monthly free credits.", "schema": { "type": "integer" } }, "X-FastAF-Cost-Version": { "schema": { "type": "string" } }, "X-Request-Id": { "description": "Unique id of this request (req_ + 32 hex). Sent on every response, errors included; quote it to support.", "schema": { "type": "string" } }, "X-FastAF-Receipt": { "description": "The receipt as `key=value` pairs separated by \"; \": request_id, endpoint, credits, free_credits, usd, usd_basis, sha256, x402_tx (\"none\" when absent). See the Receipt schema.", "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "type": [ "object", "array" ], "description": "JSON that validates against the request schema, minified. Optional schema fields may be missing or null; only fields listed in required are guaranteed to be present in a successful response. Optional nulls are omitted before validation. Answers that are not JSON, do not match the schema or exceed 64 KB return 422 extraction_failed with validation_errors and are never charged or settled." }, "example": { "title": "A Light in the Attic", "price": { "amount": 51.77, "currency": "GBP" }, "in_stock": true } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/TargetNotFound" }, "409": { "description": "spend_cap_exceeded: the call would exceed X-FastAF-Max-Spend. Nothing was charged. Body: {error, spent_usd, cap_usd, requested_usd, requested_credits, session}.", "content": { "application/json": { "schema": { "type": "object", "required": [ "error", "spent_usd", "cap_usd", "requested_usd" ], "properties": { "error": { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "string", "const": "spend_cap_exceeded" }, "message": { "type": "string" } } }, "spent_usd": { "type": "string", "description": "Already spent (and held by calls in flight) in this session; 0 without a session." }, "cap_usd": { "type": "string" }, "requested_usd": { "type": "string", "description": "List price of the refused call." }, "requested_credits": { "type": "integer", "minimum": 0 }, "session": { "type": [ "string", "null" ] } } } } } }, "422": { "$ref": "#/components/responses/ExtractionFailed" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "502": { "$ref": "#/components/responses/BadGateway" }, "503": { "$ref": "#/components/responses/DataServiceUnavailable" } }, "x-fastaf-credit-cost": 40, "x-fastaf-cost-version": "v1", "operationId": "postExtract", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "description": "POST only, JSON body: a public page url and a JSON Schema (draft 2020-12 subset: at most 8 KB, 5 levels and 50 properties, local $ref only, root type object or array). render_js (alias dynamic) and premium are optional; challenge_mode is not available.", "examples": [ { "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html", "schema": { "type": "object", "required": [ "title", "price", "in_stock" ], "properties": { "title": { "type": "string" }, "price": { "type": "object", "required": [ "amount", "currency" ], "properties": { "amount": { "type": "number" }, "currency": { "type": "string" } } }, "in_stock": { "type": "boolean" } } } } ], "additionalProperties": false, "properties": { "url": { "type": "string", "format": "uri", "pattern": "^https?://", "maxLength": 8192, "description": "Required public HTTP(S) page URL, at most 8192 characters. Same rules as scrape: private targets and login paths are refused, Zillow/eBay point to their endpoints, Booking is rendered; Reddit and Amazon pages are refused. Nothing is charged for a refused URL. No option surcharge; 40 credits per successful request.", "examples": [ "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html" ] }, "schema": { "type": "object", "additionalProperties": true, "description": "Required JSON Schema object (draft 2020-12 subset) describing the JSON to return. Root type object or array; at most 8 KB without whitespace, 5 levels deep (root included) and 50 properties in total; local $ref (#/$defs/...) only, no recursion. Keywords: type, properties, required, additionalProperties, items, prefixItems, enum, const, anyOf, oneOf, allOf, not, $defs, format, pattern, numeric and length bounds, and annotations. An invalid schema returns 400 before anything is charged. No option surcharge; 40 credits per successful request.", "examples": [ { "type": "object", "required": [ "title", "price", "in_stock" ], "properties": { "title": { "type": "string" }, "price": { "type": "object", "required": [ "amount", "currency" ], "properties": { "amount": { "type": "number" }, "currency": { "type": "string" } } }, "in_stock": { "type": "boolean" } } } ] }, "render_js": { "type": "boolean", "description": "Render JavaScript before extracting; true/false, default false (booking.com defaults true). Same price. No option surcharge; 40 credits per successful request." }, "dynamic": { "type": "boolean", "description": "Alias for render_js; cannot disagree with it. Same price. No option surcharge; 40 credits per successful request." }, "premium": { "type": "boolean", "description": "Use residential proxies; true/false, default false. Same price. No option surcharge; 40 credits per successful request." } }, "required": [ "url", "schema" ] } } } }, "parameters": [ { "name": "X-FastAF-Max-Spend", "in": "header", "required": false, "description": "Optional spending cap in USD, decimal with up to 6 places (e.g. 0.50). Alone it caps this call; with X-FastAF-Session it caps the session's running total. A call that would go over is refused with 409 spend_cap_exceeded before anything is reserved or charged. Credits are valued at the Starter list price, $0.0005 per credit.", "schema": { "type": "string", "pattern": "^\\d{1,7}(?:\\.\\d{1,6})?$", "examples": [ "0.50" ] } }, { "name": "X-FastAF-Session", "in": "header", "required": false, "description": "Optional session id (1-128 letters, digits, '.', '_', ':' or '-') for a cumulative X-FastAF-Max-Spend: what this API account spent under the same id counts toward the cap, until 24 hours after the session's last call. Requires X-FastAF-Max-Spend.", "schema": { "type": "string", "pattern": "^[A-Za-z0-9._:-]{1,128}$", "examples": [ "agent-run-42" ] } } ] } } ## Shared schemas (local $refs resolve here) { "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "API key" }, "sessionCookie": { "type": "apiKey", "in": "cookie", "name": "fastaf_session" } }, "schemas": { "ApiKey": { "type": "object", "additionalProperties": false, "required": [ "id", "prefix", "name", "status", "created_at", "last_used_at" ], "properties": { "id": { "type": "string" }, "prefix": { "type": "string", "pattern": "^faf_live_" }, "name": { "type": "string", "maxLength": 100 }, "status": { "type": "string", "enum": [ "active", "revoked" ] }, "created_at": { "type": "string" }, "last_used_at": { "type": [ "string", "null" ] } } }, "CreatedApiKey": { "type": "object", "additionalProperties": false, "required": [ "id", "prefix", "name", "status", "created_at", "last_used_at", "key", "warning" ], "properties": { "id": { "type": "string" }, "prefix": { "type": "string", "pattern": "^faf_live_" }, "name": { "type": "string", "maxLength": 100 }, "status": { "type": "string", "const": "active" }, "created_at": { "type": "string" }, "last_used_at": { "type": "null" }, "key": { "type": "string", "pattern": "^faf_live_[0-9A-Za-z]{32}$" }, "warning": { "type": "string" } } }, "RequestLogEntry": { "type": "object", "additionalProperties": false, "required": [ "id", "endpoint", "status", "credits", "duration_ms", "created_at" ], "properties": { "id": { "type": "string" }, "endpoint": { "type": "string", "enum": [ "serp", "maps", "amazon", "linkedin", "youtube", "scrape", "news", "shopping", "scholar", "jobs", "ai", "linkedin_jobs", "patents", "flights", "bing", "images", "reddit", "walmart", "zillow", "ebay", "x", "screenshot", "extract" ] }, "status": { "type": "integer" }, "credits": { "type": "integer", "minimum": 0 }, "duration_ms": { "type": "integer", "minimum": 0 }, "created_at": { "type": "string", "format": "date-time" } } }, "UsageDay": { "type": "object", "additionalProperties": false, "required": [ "day", "endpoint", "requests", "credits", "failed_requests" ], "properties": { "day": { "type": "string", "format": "date" }, "endpoint": { "type": "string", "enum": [ "serp", "maps", "amazon", "linkedin", "youtube", "scrape", "news", "shopping", "scholar", "jobs", "ai", "linkedin_jobs", "patents", "flights", "bing", "images", "reddit", "walmart", "zillow", "ebay", "x", "screenshot", "extract" ] }, "requests": { "type": "integer", "minimum": 0 }, "credits": { "type": "integer", "minimum": 0 }, "failed_requests": { "type": "integer", "minimum": 0 } } }, "Receipt": { "type": "object", "description": "Receipt of a successful data call, also in the X-FastAF-Receipt header. Added with request_id at the end of JSON object answers; other formats carry it in the header only. It describes the call and changes nothing about billing.", "required": [ "request_id", "endpoint", "credits", "free_credits", "usd", "usd_basis", "sha256", "x402_tx", "x402_network", "issued_at" ], "properties": { "request_id": { "type": "string", "pattern": "^req_[0-9a-f]{32}$", "description": "Same value as the X-Request-Id header." }, "endpoint": { "type": "string" }, "credits": { "type": [ "integer", "null" ], "minimum": 0, "description": "Credits taken for the call (keyed API); null over x402." }, "free_credits": { "type": [ "integer", "null" ], "minimum": 0, "description": "The part of credits paid with the monthly free credits; null over x402." }, "usd": { "type": "string", "pattern": "^\\d+\\.\\d{6}$", "description": "Cost in USD: the x402 price paid, or the paid credits (credits minus free_credits) at the Starter pack rate ($10 / 20,000 credits), the highest rate per credit." }, "usd_basis": { "type": "string", "enum": [ "x402_price", "starter_pack_rate" ] }, "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$", "description": "sha256 (hex) of the data. JSON object answers: JSON.stringify of the body without request_id and receipt. Any other format: the exact bytes received." }, "x402_tx": { "type": [ "string", "null" ], "description": "x402 settlement transaction hash; null on the keyed API." }, "x402_network": { "type": [ "string", "null" ], "description": "CAIP-2 network of the x402 settlement, e.g. eip155:8453." }, "issued_at": { "type": "string", "format": "date-time" } } }, "Error": { "type": "object", "required": [ "error" ], "properties": { "blocked": { "type": "boolean", "const": true, "description": "Present when the site or data source blocked the call (captcha, bot check, empty page, or HTTP 403/429/503 on scrape and serp). Never charged: credits are refunded and x402 payments are not settled. Also sent as the X-FastAF-Blocked header." }, "reason": { "type": "string", "enum": [ "challenge", "captcha", "empty", "too_short", "incomplete", "not_data", "serp_blocked", "http_403", "http_429", "http_503" ], "description": "Why the call was flagged as blocked: challenge (bot check page), captcha (reCAPTCHA/hCaptcha widget), empty or too_short (no content), incomplete (results missing), not_data (a web page in place of JSON), serp_blocked (Google's unusual-traffic or captcha page without organic results), http_403 / http_429 / http_503 (the data source refused the call)." }, "example": { "type": "string", "format": "uri", "description": "A complete valid GET request URL for this endpoint, included with invalid input responses." }, "example_url": { "type": "string", "format": "uri", "description": "A complete valid GET example for this endpoint, included with parameter validation errors." }, "examples": { "type": "array", "items": { "type": "string", "format": "uri" }, "description": "Valid URLs for alternative operations, such as YouTube transcript and search." }, "accepted_aliases": { "type": "array", "items": { "type": "string" }, "description": "Accepted parameter aliases; see parameter descriptions for their canonical names and precedence." }, "error": { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "string" }, "message": { "type": "string" } } } } }, "PaymentRequired": { "allOf": [ { "type": "object", "required": [ "error" ], "properties": { "error": { "type": "string", "description": "Error code (v2 PaymentRequired.error)." }, "error_details": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } } } } }, { "type": "object", "required": [ "x402Version", "accepts" ], "properties": { "x402Version": { "type": "integer", "const": 2, "description": "Same as PAYMENT-REQUIRED: x402 v2." }, "resource": { "type": "object", "required": [ "url", "description", "mimeType" ], "description": "The PAYMENT-REQUIRED resource with the full discovery metadata (the compact header keeps url, first-sentence description, mimeType, serviceName, tags and iconUrl).", "properties": { "url": { "type": "string", "format": "uri" }, "description": { "type": "string" }, "mimeType": { "type": "string" }, "serviceName": { "type": "string", "example": "FastAF" }, "tags": { "type": "array", "maxItems": 5, "items": { "type": "string" }, "description": "Endpoint category followed by search tags." }, "iconUrl": { "type": "string", "format": "uri" }, "homepage": { "type": "string", "format": "uri", "example": "https://fastaf.co" }, "website": { "type": "string", "format": "uri", "example": "https://fastaf.co" }, "docsUrl": { "type": "string", "format": "uri" }, "openApiUrl": { "type": "string", "format": "uri", "example": "https://api.fastaf.co/openapi.json" } } }, "extensions": { "type": "object", "description": "The full protocol extensions; PAYMENT-REQUIRED carries a compact Bazaar declaration (input example and its schema). Per-operation x-x402-discovery contains the concrete Bazaar info and JSON Schema.", "properties": { "bazaar": { "type": "object", "required": [ "info", "schema" ], "properties": { "info": { "type": "object", "required": [ "input" ], "properties": { "input": { "type": "object" }, "output": { "type": "object" } } }, "schema": { "type": "object", "description": "JSON Schema (2020-12) validating info, including input parameters and output.example." }, "routeTemplate": { "type": "string" } } } } }, "accepts": { "type": "array", "minItems": 1, "description": "The x402 v2 requirements, identical to PAYMENT-REQUIRED. Present on payment challenges, not settlement failures.", "items": { "type": "object", "required": [ "scheme", "network", "amount", "payTo", "asset", "maxTimeoutSeconds", "extra" ], "properties": { "scheme": { "type": "string", "const": "exact" }, "network": { "type": "string", "pattern": "^eip155:[0-9]+$", "description": "CAIP-2 network identifier." }, "amount": { "type": "string", "pattern": "^[0-9]+$", "description": "Price in atomic USDC units." }, "payTo": { "type": "string" }, "asset": { "type": "string" }, "maxTimeoutSeconds": { "type": "integer" }, "extra": { "type": "object", "additionalProperties": true } } } }, "price": { "type": "object", "required": [ "usd", "asset", "network" ], "properties": { "usd": { "type": "string", "pattern": "^[0-9]+\\.[0-9]{6}$" }, "credits": { "type": "integer", "minimum": 1 }, "asset": { "type": "string", "const": "USDC" }, "network": { "type": "string", "description": "CAIP-2 network identifier." } } }, "how_to_pay": { "type": "string" }, "with_a_key": { "type": "string" }, "docs": { "type": "string", "format": "uri" } } } ] } }, "responses": { "BadRequest": { "description": "Invalid request or parameters.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Unauthorized": { "description": "Missing, invalid or revoked API key. Data-route errors include error.help with signup and API-key instructions. Pay-per-call clients must start at /x402/v1/{endpoint}; /v1 never accepts payment headers.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }, "headers": { "WWW-Authenticate": { "schema": { "type": "string", "const": "Bearer" } } } }, "PaymentRequired": { "description": "The account has insufficient credits.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "Forbidden": { "description": "The account is suspended or email verification is required before data calls.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "TargetNotFound": { "description": "target_not_found: the requested resource was not found (Amazon product/offer: Product not found). No credits are consumed. Check the identifier or URL.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "ExtractionFailed": { "description": "extraction_failed: the page could not be extracted as JSON, the JSON did not match the schema (validation_errors lists why), or it exceeded 64 KB. Never charged; on x402 never settled.", "content": { "application/json": { "schema": { "type": "object", "required": [ "error", "reason", "validation_errors" ], "properties": { "error": { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "string", "const": "extraction_failed" }, "message": { "type": "string" } } }, "reason": { "type": "string", "enum": [ "unparsable", "schema_mismatch", "too_large" ] }, "validation_errors": { "type": "array", "maxItems": 20, "description": "Schema validation errors (schema_mismatch only), as JSON pointers into the extracted data.", "items": { "type": "object", "required": [ "path", "message" ], "properties": { "path": { "type": "string", "examples": [ "#/rating" ] }, "message": { "type": "string" } } } } } } } } }, "TargetUnavailable": { "description": "target_unavailable: the source returned 410 or an empty response, without a definitive not-found result. Nothing charged.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "TooManyRequests": { "description": "A rate or concurrency limit was reached.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadGateway": { "description": "The upstream request failed, or the site answered with a block (target_blocked: captcha, bot check, empty page) or no data (no_data). Never charged. A blocked answer adds blocked: true and reason to the body and the X-FastAF-Blocked header.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }, "headers": { "X-FastAF-Blocked": { "description": "The block reason, on blocked calls only.", "schema": { "type": "string", "enum": [ "challenge", "captcha", "empty", "too_short", "incomplete", "not_data", "serp_blocked", "http_403", "http_429", "http_503" ], "description": "Why the call was flagged as blocked: challenge (bot check page), captcha (reCAPTCHA/hCaptcha widget), empty or too_short (no content), incomplete (results missing), not_data (a web page in place of JSON), serp_blocked (Google's unusual-traffic or captcha page without organic results), http_403 / http_429 / http_503 (the data source refused the call)." } } } }, "ServiceUnavailable": { "description": "The service is temporarily unavailable.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "InternalServerError": { "description": "The request failed unexpectedly.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "DataServiceUnavailable": { "description": "Temporarily unavailable; always with Retry-After and never charged (credits are refunded). Upstream outages use {error: {code: 'upstream_timeout' | 'upstream_unavailable', message, stage: 'upstream_fetch', retry_after: 5}}; other 503s keep the Error shape (capacity_unavailable, reservation_expired, service_unavailable).", "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer", "minimum": 1 } } }, "content": { "application/json": { "schema": { "anyOf": [ { "type": "object", "additionalProperties": false, "required": [ "error" ], "properties": { "error": { "type": "object", "additionalProperties": false, "required": [ "code", "message", "stage", "retry_after" ], "properties": { "code": { "type": "string", "enum": [ "upstream_timeout", "upstream_unavailable" ] }, "message": { "type": "string" }, "stage": { "type": "string", "const": "upstream_fetch" }, "retry_after": { "type": "integer", "const": 5, "description": "Same value as the Retry-After header, in seconds." } } }, "blocked": { "type": "boolean", "const": true, "description": "Present on scrape and serp when the data source answered HTTP 503: reported as a block. Never charged." }, "reason": { "type": "string", "const": "http_503", "description": "Why the call was flagged as blocked; also sent as the X-FastAF-Blocked header." } }, "example": { "error": { "code": "upstream_timeout", "message": "The data source did not answer in time. Nothing was charged; retry after Retry-After seconds.", "stage": "upstream_fetch", "retry_after": 5 } } }, { "$ref": "#/components/schemas/Error" } ] } } } }, "X402DemoPaymentRequired": { "description": "Testnet payment required: x402 v2 exact, eip155:84532 (Base Sepolia), 1000 atomic test USDC (0.001). No real funds or API key. PAYMENT-REQUIRED is authoritative; retry with PAYMENT-SIGNATURE. Settlement failures return 402 with PAYMENT-RESPONSE and no data.", "headers": { "PAYMENT-REQUIRED": { "description": "Base64-encoded x402 v2 testnet challenge.", "schema": { "type": "string" } }, "PAYMENT-RESPONSE": { "description": "Base64-encoded settlement failure receipt.", "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "anyOf": [ { "$ref": "#/components/schemas/Error" }, { "allOf": [ { "$ref": "#/components/schemas/PaymentRequired" }, { "type": "object", "properties": { "x402Version": { "type": "integer", "const": 2 }, "demo": { "type": "boolean", "const": true }, "network": { "type": "string", "const": "base-sepolia" }, "resource": { "$ref": "#/components/schemas/PaymentRequired/allOf/1/properties/resource" }, "accepts": { "$ref": "#/components/schemas/PaymentRequired/allOf/1/properties/accepts" }, "extensions": { "type": "object" }, "price": { "type": "object", "properties": { "usd": { "const": "0.001000" }, "credits": { "const": 0 }, "asset": { "const": "USDC" }, "network": { "const": "eip155:84532" } } } } } ] } ] } } } }, "X402PaymentRequired": { "description": "Payment required. Decode PAYMENT-REQUIRED (base64 JSON) for the authoritative x402 v2 accepts[].amount in USDC atomic units, network, asset and payTo. The JSON body is the same v2 PaymentRequired (x402Version, resource, accepts, extensions) plus human-readable fields. Sign it with an x402 v2 client and retry with PAYMENT-SIGNATURE. Start at /x402/v1/*, not /v1/*. A failed settlement also returns 402 (settlement_failed) with PAYMENT-RESPONSE instead of data, without a payment challenge.", "headers": { "PAYMENT-REQUIRED": { "description": "Base64-encoded x402 v2 payment challenge (present on unpaid requests).", "schema": { "type": "string" } }, "PAYMENT-RESPONSE": { "description": "Base64-encoded settlement failure receipt, when settlement fails.", "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "anyOf": [ { "$ref": "#/components/schemas/PaymentRequired" }, { "$ref": "#/components/schemas/Error" } ] } } } } } }