{"openapi":"3.1.0","info":{"title":"ScrapeWhale API","version":"1.0.0","summary":"Web data for marketing agents: traffic, ads, social profiles, and clean markdown from any URL or file — every endpoint returns structured JSON and/or agent-ready markdown.","description":"Web data for marketing agents: traffic, ads, social profiles, and clean markdown from any URL or file — every endpoint returns structured JSON and/or agent-ready markdown.\n\nEvery response is built for agents: structured `data` for post-processing,\nclean `markdown` for dropping straight into a context window — your choice\nper request. Machine-readable spec: [/openapi.json](/openapi.json) · agent\nsummary: [/llms.txt](/llms.txt).\n\n# Getting started\n\n## Quick start\n\nCreate an API key at [/settings/apikeys](/settings/apikeys) — new accounts get\n**10 free credits**, no card required. Then make your first call:\n\n```bash\ncurl 'https://scrapewhale.dev/api/v1/traffic?domain=nike.com' \\\n  -H 'Authorization: Bearer <api-key>'\n```\n\nOr pull a full brand dossier — logo, traffic, authority, ads, and the homepage\nas markdown, in one call:\n\n```bash\ncurl 'https://scrapewhale.dev/api/v1/brand?domain=nike.com' \\\n  -H 'Authorization: Bearer <api-key>'\n```\n\n## Authentication\n\nCreate an API key at **/settings/apikeys**, then send it on every request:\n\n```\nAuthorization: Bearer <api-key>\n```\n\n(`x-api-key: <api-key>` also works.) Keys are rate-limited to 60 requests\nper minute; credits are the real spend cap. Logged-in users can also run every\nendpoint from the **Playground** at [/playground](/playground) — same\nendpoints, same credits.\n\n## Credits\n\nEvery successful request consumes credits from your balance (new accounts\nstart with 10 free credits; credit packs never expire):\n\n| Endpoints | Credits |\n| --- | --- |\n| URL / file → markdown, search, maps, trends, social profiles, X/Twitter posts, YouTube video/channel/transcript/search, TikTok Shop lookups, Shopify catalogue, Google ad creative/advertiser, traffic & SEO metrics, domain facts, Chrome Web Store | 1 |\n| Ads endpoints, the TikTok Shop catalog, and AI Overview (heavy upstream crawls/renders) | 2 |\n\n**Failed requests are refunded automatically** — you are never charged for an\nerror. **Cache hits are free**: data endpoints serve recently-fetched public\ndata (6–24h freshness windows; logos 7 days) from a shared cache at no credit\ncost — the response carries `\"cached\": true` and `\"creditsCharged\": 0`.\n\n## Output formats\n\nExtraction endpoints accept `?format=json|markdown|both` (default `both`):\n\n- `json` — structured payload only (`data`)\n- `markdown` — clean markdown only (`markdown`)\n- `both` — both fields in one response\n\nBoth artifacts are stored with the conversion and can be re-fetched later via\n`GET /api/v1/conversions/{id}`.\n\n## Errors\n\nErrors are JSON `{ \"error\": \"<message>\", \"code\": \"<code>\" }`:\n\n| Status | Meaning |\n| --- | --- |\n| 400 | Invalid parameters |\n| 401 | Missing or invalid API key |\n| 402 | Insufficient credits |\n| 404 | Not found |\n| 422 | Extraction/conversion failed (`code` carries the failure category; credits refunded) |\n| 429 | Rate limit exceeded |\n\nFile uploads can additionally return 413 (over 10 MB) or 415 (unsupported or\nblocked type — HTML files are rejected; convert web pages by URL instead).\n\n# Integrations\n\n## MCP server\n\nA hosted MCP server at `https://scrapewhale.dev/mcp` (Streamable HTTP)\nexposes every endpoint as tools, grouped by platform (`youtube`, `ads`,\n`domain_intel`, `google_trends`, …), plus `brand_dossier` and\n`get_result`. Nothing to install: sign in with your ScrapeWhale account,\nor send the same API key as REST. Tool calls cost the same credits as the\nmatching endpoint.\n\n**Claude (claude.ai / Desktop)** — Settings → Connectors → *Add custom\nconnector*, URL `https://scrapewhale.dev/mcp`, then sign in and approve.\nOther clients with OAuth support (e.g. ChatGPT) use the same sign-in flow.\nConnected apps can be disconnected at [/settings/apikeys](/settings/apikeys).\n\n**Claude Code** — sign in with your account (no key needed):\n\n```bash\nclaude mcp add --transport http scrapewhale https://scrapewhale.dev/mcp\n```\n\nThen run `/mcp` inside Claude Code, pick **scrapewhale** → *Authenticate*,\nand approve in the browser. Or use an API key instead (handy for CI and\nheadless runs):\n\n```bash\nclaude mcp add --transport http scrapewhale https://scrapewhale.dev/mcp \\\n  --header 'Authorization: Bearer <api-key>'\n```\n\nAdd `--scope user` to make it available in every project.\n\n**Codex** (`~/.codex/config.toml`, with the key in `SCRAPEWHALE_API_KEY`)\n\n```toml\n[mcp_servers.scrapewhale]\nurl = \"https://scrapewhale.dev/mcp\"\nbearer_token_env_var = \"SCRAPEWHALE_API_KEY\"\n```\n\n**Cursor** and other clients that take JSON config (`.cursor/mcp.json`)\n\n```json\n{\n  \"mcpServers\": {\n    \"scrapewhale\": {\n      \"url\": \"https://scrapewhale.dev/mcp\",\n      \"headers\": { \"Authorization\": \"Bearer <api-key>\" }\n    }\n  }\n}\n```\n\nTools return markdown by default; pass `format: \"json\"` for the structured\ndata. Local file conversion is not available over the hosted server — upload\nfiles with `POST /api/v1/markdown/file`.\n\n## Using ScrapeWhale in Claude & ChatGPT\n\nOnce connected, ask in plain language — the assistant picks the tool.\nExample prompts:\n\n- \"Build a brand dossier for allbirds.com: traffic, authority, the ads\n  they're running, and what their homepage says.\"\n- \"What ads is Liquid Death running on Facebook right now? Summarize the\n  main angles.\"\n- \"Compare estimated monthly traffic and traffic sources for notion.so,\n  coda.io, and clickup.com.\"\n- \"Pull the transcript of this YouTube video and list the product claims:\n  https://www.youtube.com/watch?v=…\"\n- \"Find coffee roasters in Austin on Google Maps with a rating above 4.5.\"\n- \"What's trending on Google in the US today, and how has interest in\n  'protein coffee' changed over the past year?\"\n- \"Read https://example.com/pricing and turn it into a comparison table.\"\n\n**What it can't do:** it reads public data only — no logging in to other\nsites, no posting or changing anything. Every tool is read-only.\n\n**Limits:** each tool call spends the same credits as its API endpoint\n(most cost 1, ads and AI Overview 2, the brand dossier up to 6); failed\ncalls are refunded and recently fetched data is free. Results over 50,000\ncharacters are truncated, with an `id` to fetch the rest via\n`get_result`. API keys are limited to 60 requests per minute.\n\n**Disconnect:** remove the connector in your AI app, or revoke it under\nConnected apps at [/settings/apikeys](/settings/apikeys).\n\n**Support:** email support@scrapewhale.dev or use [/contact](/contact)."},"servers":[{"url":"https://scrapewhale.dev"}],"tags":[{"name":"Web"},{"name":"Search"},{"name":"Maps"},{"name":"Trends"},{"name":"Traffic & SEO"},{"name":"Domain"},{"name":"Chrome Web Store"},{"name":"Ads"},{"name":"Brand"},{"name":"Social"},{"name":"TikTok Shop"},{"name":"Shopify"},{"name":"Conversions"}],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"paths":{"/api/v1/markdown/url":{"get":{"tags":["Web"],"summary":"URL to markdown","description":"Any public web page as clean, LLM-ready markdown — headings, lists, tables, links, and images preserved; nav, ads, and boilerplate removed. JavaScript-rendered pages included. Plain page reading only: YouTube, X, Facebook, and other structured sources have their own endpoints and are not auto-detected here. Recently read pages are served from cache for free.\n\n**Credits: 1** (refunded on failure).","operationId":"getMarkdownUrl","parameters":[{"name":"url","in":"query","required":true,"description":"The web page to convert.","schema":{"type":"string","format":"uri"},"example":"https://example.com/article"}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/markdown/file":{"post":{"tags":["Web"],"summary":"File to markdown","description":"Upload a document and get it back as markdown: PDF, Word, Excel, CSV, OpenDocument, Apple Numbers, and images (scanned PDFs and images are OCR'd). `multipart/form-data` with a `file` field, 10 MB cap; HTML files are rejected — use the URL endpoint for web pages. The upload is validated before any credit is charged.\n\n**Credits: 1** (refunded on failure).","operationId":"markdownFile","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"The document to convert (PDF, Word, Excel, CSV, image, …)."}}}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/search":{"get":{"tags":["Search"],"summary":"Google web search","description":"Google web search results for any query: organic results (title, link, snippet, position), answer box, knowledge graph, videos, People Also Ask, and related searches. Raw payload in `data`, a clean readable digest in `markdown`. Field fullness varies by upstream backend (People Also Ask and videos can come back empty). Results are cached for 1 hour — repeat queries are free.\n\n**Credits: 1** (refunded on failure).","operationId":"getSearch","parameters":[{"name":"q","in":"query","required":true,"description":"The search query.","schema":{"type":"string","maxLength":512},"example":"best running shoes 2026"},{"name":"gl","in":"query","required":false,"description":"Country code (Google gl), e.g. \"us\", \"gb\", \"de\".","schema":{"type":"string","default":"us"}},{"name":"hl","in":"query","required":false,"description":"Language code (Google hl), e.g. \"en\", \"es\".","schema":{"type":"string","default":"en"}},{"name":"num","in":"query","required":false,"description":"Results per page (1–20, default 10).","schema":{"type":"integer","minimum":1,"maximum":20,"default":10}},{"name":"page","in":"query","required":false,"description":"Result page (1–10, default 1).","schema":{"type":"integer","minimum":1,"maximum":10,"default":1}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/search/ai-overview":{"get":{"tags":["Search"],"summary":"Google AI Overview","description":"Google’s full AI Overview for a query — the rich multi-source answer shown above the results: ordered text blocks (paragraphs, headings, lists) with `[n]` citation markers linking into a references list of cited sources. The key input for answer-engine (GEO) monitoring: see what Google’s AI says about a topic and which domains it cites. Overviews exist for roughly half of queries and Google generates them probabilistically — when none is produced the request fails with `empty_result` and the credits are refunded (retrying later can succeed). Cached for 24 hours.\n\n**Credits: 2** (refunded on failure).","operationId":"getSearchAi-overview","parameters":[{"name":"q","in":"query","required":true,"description":"The search query.","schema":{"type":"string","maxLength":512},"example":"best crm for small business"},{"name":"gl","in":"query","required":false,"description":"Country code (Google gl), e.g. \"us\", \"gb\", \"de\".","schema":{"type":"string","default":"us"}},{"name":"hl","in":"query","required":false,"description":"Language code (Google hl), e.g. \"en\", \"es\".","schema":{"type":"string","default":"en"}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/maps":{"get":{"tags":["Maps"],"summary":"Google Maps place search","description":"Google Maps place search for any query: name, address, coordinates, rating and review count, type, website, phone, price level, opening hours, booking links, and whether the listing is claimed by its owner (`claimed: false` is a lead-gen signal). Each place carries a `cid` usable with `/api/v1/maps/place`. Without `ll` results are biased by the scraper exit IP’s location — pass `ll` for deterministic results, especially when paginating.\n\n**Credits: 1** (refunded on failure).","operationId":"getMaps","parameters":[{"name":"q","in":"query","required":true,"description":"The place search query.","schema":{"type":"string","maxLength":512},"example":"coffee shops near 5th avenue"},{"name":"ll","in":"query","required":false,"description":"Location bias as `@lat,lng,zoom`, e.g. `@40.7504,-73.9824,14z`.","schema":{"type":"string"},"example":"@40.7504,-73.9824,14z"},{"name":"gl","in":"query","required":false,"description":"Country code, e.g. \"us\", \"gb\", \"de\".","schema":{"type":"string","default":"us"}},{"name":"hl","in":"query","required":false,"description":"Language code, e.g. \"en\", \"es\".","schema":{"type":"string","default":"en"}},{"name":"page","in":"query","required":false,"description":"Page of 20 places (1–5, default 1). Deeper pages widen the search radius.","schema":{"type":"integer","minimum":1,"maximum":5,"default":1}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/maps/place":{"get":{"tags":["Maps"],"summary":"Google Maps place details","description":"Full details for one place by `cid` (from `/api/v1/maps` or a `maps.google.com/?cid=` link) or `fid`: everything the search returns plus the owner-written long description and the canonical Maps URL.\n\nProvide exactly one of: `cid`, `fid`.\n\n**Credits: 1** (refunded on failure).","operationId":"getMapsPlace","parameters":[{"name":"cid","in":"query","required":false,"description":"Place CID (decimal). Provide `cid` or `fid`.","schema":{"type":"string","pattern":"^\\d+$"},"example":"6182067377655413673"},{"name":"fid","in":"query","required":false,"description":"Place FID (`0x…:0x…`), alternative to `cid`.","schema":{"type":"string"}},{"name":"gl","in":"query","required":false,"description":"Country code, e.g. \"us\".","schema":{"type":"string","default":"us"}},{"name":"hl","in":"query","required":false,"description":"Language code, e.g. \"en\".","schema":{"type":"string","default":"en"}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/trends/interest":{"get":{"tags":["Trends"],"summary":"Google Trends — interest over time","description":"Search-interest timeline for up to 5 comma-separated keywords, compared against each other like the Trends UI. Values are Google’s normalized 0–100 indexes, not absolute volumes.\n\n**Credits: 1** (refunded on failure).","operationId":"getTrendsInterest","parameters":[{"name":"q","in":"query","required":true,"description":"Keyword(s) — up to 5, comma-separated.","schema":{"type":"string","maxLength":256},"example":"nextjs,nuxt"},{"name":"geo","in":"query","required":false,"description":"ISO country (\"US\"), subregion (\"US-CA\"), or empty for worldwide.","schema":{"type":"string","default":"US"}},{"name":"time","in":"query","required":false,"description":"Timeframe in Trends syntax: \"now 1-H\", \"now 7-d\", \"today 1-m\", \"today 3-m\", \"today 12-m\", \"today 5-y\", \"all\", or \"YYYY-MM-DD YYYY-MM-DD\".","schema":{"type":"string","default":"today 12-m"}},{"name":"cat","in":"query","required":false,"description":"Trends category id (0 = all).","schema":{"type":"integer","default":0}},{"name":"gprop","in":"query","required":false,"description":"Property: omit for web search, or \"images\", \"news\", \"youtube\", \"froogle\".","schema":{"type":"string","enum":["images","news","youtube","froogle"]}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/trends/related":{"get":{"tags":["Trends"],"summary":"Google Trends — related queries","description":"Related queries for a keyword: top queries (0–100 index) and rising queries (growth percentages; \"Breakout\" means above 5000% growth). Useful for keyword expansion and spotting emerging demand.\n\n**Credits: 1** (refunded on failure).","operationId":"getTrendsRelated","parameters":[{"name":"q","in":"query","required":true,"description":"The keyword.","schema":{"type":"string","maxLength":128},"example":"protein powder"},{"name":"geo","in":"query","required":false,"description":"ISO country (\"US\"), subregion (\"US-CA\"), or empty for worldwide.","schema":{"type":"string","default":"US"}},{"name":"time","in":"query","required":false,"description":"Timeframe in Trends syntax (see /trends/interest).","schema":{"type":"string","default":"today 12-m"}},{"name":"cat","in":"query","required":false,"description":"Trends category id (0 = all).","schema":{"type":"integer","default":0}},{"name":"gprop","in":"query","required":false,"description":"Property: omit for web search, or \"images\", \"news\", \"youtube\", \"froogle\".","schema":{"type":"string","enum":["images","news","youtube","froogle"]}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/trends/geo":{"get":{"tags":["Trends"],"summary":"Google Trends — interest by region","description":"Where a keyword is searched most: regions ranked by normalized interest (0–100). `resolution` picks the granularity — COUNTRY, REGION, DMA, or CITY (CITY only returns data for subregion geos like `geo=US-CA`, and sparsely).\n\n**Credits: 1** (refunded on failure).","operationId":"getTrendsGeo","parameters":[{"name":"q","in":"query","required":true,"description":"The keyword.","schema":{"type":"string","maxLength":128},"example":"vercel"},{"name":"geo","in":"query","required":false,"description":"ISO country (\"US\"), subregion (\"US-CA\"), or empty for worldwide.","schema":{"type":"string","default":"US"}},{"name":"resolution","in":"query","required":false,"description":"Region granularity.","schema":{"type":"string","enum":["COUNTRY","REGION","DMA","CITY"]}},{"name":"time","in":"query","required":false,"description":"Timeframe in Trends syntax (see /trends/interest).","schema":{"type":"string","default":"today 12-m"}},{"name":"cat","in":"query","required":false,"description":"Trends category id (0 = all).","schema":{"type":"integer","default":0}},{"name":"gprop","in":"query","required":false,"description":"Property: omit for web search, or \"images\", \"news\", \"youtube\", \"froogle\".","schema":{"type":"string","enum":["images","news","youtube","froogle"]}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/trends/trending":{"get":{"tags":["Trends"],"summary":"Google Trends — trending now","description":"Currently trending searches for a country, each with an approximate traffic figure and related news links. Cached for 1 hour — trending data moves fast.\n\n**Credits: 1** (refunded on failure).","operationId":"getTrendsTrending","parameters":[{"name":"geo","in":"query","required":false,"description":"2-letter country code.","schema":{"type":"string","default":"US"},"example":"US"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/traffic":{"get":{"tags":["Traffic & SEO"],"summary":"Estimated website traffic","description":"Traffic estimate for a domain: global/country/category rank, monthly visits, engagement (bounce rate, pages per visit, visit duration), traffic sources, top countries, top keywords, and AI-assistant-referred traffic with sample prompts.\n\n**Credits: 1** (refunded on failure).","operationId":"getTraffic","parameters":[{"name":"domain","in":"query","required":true,"description":"The website to analyze. Accepts a bare domain or a full URL.","schema":{"type":"string"},"example":"nike.com"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/seo/authority":{"get":{"tags":["Traffic & SEO"],"summary":"Domain authority (Ahrefs Domain Rating)","description":"The domain's Ahrefs Domain Rating (0–100). The response includes Ahrefs' license link, which must be preserved when the metric is displayed.\n\n**Credits: 1** (refunded on failure).","operationId":"getSeoAuthority","parameters":[{"name":"domain","in":"query","required":true,"description":"The domain to rate. Accepts a bare domain or a full URL.","schema":{"type":"string"},"example":"nike.com"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/seo/organic":{"get":{"tags":["Traffic & SEO"],"summary":"Organic search footprint","description":"The domain's organic-search footprint from a major SEO index (US database): number of organic keywords it ranks for, estimated monthly organic visits, traffic cost (what the same traffic would cost in Google Ads, USD/month), and organic rank. A domain the index has never seen fails with `empty_result` (refunded).\n\n**Credits: 1** (refunded on failure).","operationId":"getSeoOrganic","parameters":[{"name":"domain","in":"query","required":true,"description":"The domain to analyze. Accepts a bare domain or a full URL.","schema":{"type":"string"},"example":"nike.com"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/seo/backlinks":{"get":{"tags":["Traffic & SEO"],"summary":"Backlink counts","description":"Backlink counts from a major SEO index by scope: root domain (the headline number), hostname, and exact URL. A domain the index has never seen reports zeros.\n\n**Credits: 1** (refunded on failure).","operationId":"getSeoBacklinks","parameters":[{"name":"domain","in":"query","required":true,"description":"The domain to analyze. Accepts a bare domain or a full URL.","schema":{"type":"string"},"example":"nike.com"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/domain/registration":{"get":{"tags":["Domain"],"summary":"Domain registration facts (RDAP)","description":"Registration facts via RDAP: registered / expiry / last-updated dates, computed domain age, registrar, nameservers, DNSSEC, and status codes. Domain age is a standard trust signal for a brand dossier. TLDs without an RDAP service (some ccTLDs) fail with `empty_result` (refunded). Cached for 7 days.\n\n**Credits: 1** (refunded on failure).","operationId":"getDomainRegistration","parameters":[{"name":"domain","in":"query","required":true,"description":"The domain to look up. Accepts a bare domain or a full URL.","schema":{"type":"string"},"example":"nike.com"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/agent-ready":{"get":{"tags":["Domain"],"summary":"Agent-readiness probe","description":"Whether a site publishes the agent-facing files AI agents look for: `/llms.txt`, `/agents.md`, and the `/.well-known/ucp` Universal Commerce Protocol merchant profile (with its versions, capabilities, payment handlers, and MCP endpoint when advertised). Follows redirects; HTML soft-404 pages count as absent. Shopify stores publish all three by default.\n\n**Credits: 1** (refunded on failure).","operationId":"getAgent-ready","parameters":[{"name":"domain","in":"query","required":true,"description":"The site to probe. Accepts a bare domain or a full URL.","schema":{"type":"string"},"example":"nike.com"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/chrome-store/extension":{"get":{"tags":["Chrome Web Store"],"summary":"Chrome Web Store extension listing","description":"Listing snapshot for a Chrome Web Store extension: name, rating and rating count, user count, category, current version, publish date, homepage, and icon. Identify the extension by its 32-character `id` or by its store `url`.\n\nProvide exactly one of: `id`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getChrome-storeExtension","parameters":[{"name":"id","in":"query","required":false,"description":"32-character extension id.","schema":{"type":"string","pattern":"^[a-p]{32}$"},"example":"hjbfbllnfhppnhjdhhbmjabikmkfekgf"},{"name":"url","in":"query","required":false,"description":"Store URL (`chromewebstore.google.com/detail/…`), alternative to `id`.","schema":{"type":"string","format":"uri"}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/chrome-store/reviews":{"get":{"tags":["Chrome Web Store"],"summary":"Chrome Web Store extension reviews","description":"Reviews for a Chrome Web Store extension, newest first, 100 per page: author, rating, text, date, extension version, language, and the developer reply when present. Voice-of-customer and competitor research in one call. `has_more: true` means more pages exist than `max_pages` fetched.\n\nProvide exactly one of: `id`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getChrome-storeReviews","parameters":[{"name":"id","in":"query","required":false,"description":"32-character extension id.","schema":{"type":"string","pattern":"^[a-p]{32}$"},"example":"hjbfbllnfhppnhjdhhbmjabikmkfekgf"},{"name":"url","in":"query","required":false,"description":"Store URL (`chromewebstore.google.com/detail/…`), alternative to `id`.","schema":{"type":"string","format":"uri"}},{"name":"max_pages","in":"query","required":false,"description":"Pages of 100 reviews to fetch (1–10, default 1).","schema":{"type":"integer","minimum":1,"maximum":10,"default":1}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/ads/meta":{"get":{"tags":["Ads"],"summary":"Ads a Facebook page is running (Meta Ad Library)","description":"Active and recent ads for a Facebook page from the Meta Ad Library, including creative text, CTA, format, dates, and the raw ad nodes in `data`. Identify the page by numeric `page_id`, by page `slug`, or by page `url` — slugs/URLs are resolved to the page id internally at no extra credit cost. `total_count` reports the full Ad Library count even when fewer ads are fetched.\n\nProvide exactly one of: `page_id`, `slug`, `url`.\n\n**Credits: 2** (refunded on failure).","operationId":"getAdsMeta","parameters":[{"name":"page_id","in":"query","required":false,"description":"Numeric Facebook page id (fastest — skips resolution).","schema":{"type":"string","pattern":"^\\d+$"},"example":"15087023444"},{"name":"slug","in":"query","required":false,"description":"Facebook page slug, e.g. `nike` for facebook.com/nike.","schema":{"type":"string"},"example":"nike"},{"name":"url","in":"query","required":false,"description":"Full Facebook page URL.","schema":{"type":"string","format":"uri"},"example":"https://www.facebook.com/nike"},{"name":"max_pages","in":"query","required":false,"description":"Pages of 30 ads to fetch (1–10, default 3).","schema":{"type":"integer","minimum":1,"maximum":10,"default":3}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/ads/google":{"get":{"tags":["Ads"],"summary":"Ads a domain is running (Google Ads Transparency Center)","description":"Ad creatives a domain is running, scraped from Google's Ads Transparency Center (which has no official API). Returns creative ids with Transparency Center links in markdown and the raw creative items in `data`. 40 creatives per page.\n\n**Credits: 2** (refunded on failure).","operationId":"getAdsGoogle","parameters":[{"name":"domain","in":"query","required":true,"description":"The advertiser domain. Accepts a bare domain or a full URL.","schema":{"type":"string"},"example":"nike.com"},{"name":"max_pages","in":"query","required":false,"description":"Pages of 40 creatives to fetch (1–20, default 3).","schema":{"type":"integer","minimum":1,"maximum":20,"default":3}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/ads/google/creative":{"get":{"tags":["Ads"],"summary":"Google ad creative detail","description":"One creative from the Google Ads Transparency Center: format (text / image / video), every preview variant, first and last shown dates, the regions it ran in, and the advertiser block. Use the `AR…` / `CR…` ids from `/api/v1/ads/google` items. Google does not expose landing URLs for any format.\n\n**Credits: 1** (refunded on failure).","operationId":"getAdsGoogleCreative","parameters":[{"name":"advertiser_id","in":"query","required":true,"description":"Advertiser id (`AR…`), key `1` of an `/ads/google` item.","schema":{"type":"string","pattern":"^AR\\d+$"},"example":"AR01371945870127267841"},{"name":"creative_id","in":"query","required":true,"description":"Creative id (`CR…`), key `2` of an `/ads/google` item.","schema":{"type":"string","pattern":"^CR\\d+$"},"example":"CR07636846834660409345"},{"name":"include_advertiser","in":"query","required":false,"description":"Set `false` to skip the embedded advertiser lookup.","schema":{"type":"string","enum":["true","false"],"default":"true"}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/ads/google/advertiser":{"get":{"tags":["Ads"],"summary":"Google Ads advertiser identity","description":"Who is behind an `AR…` advertiser id in the Google Ads Transparency Center: display name, legal name, country, and verification status.\n\n**Credits: 1** (refunded on failure).","operationId":"getAdsGoogleAdvertiser","parameters":[{"name":"advertiser_id","in":"query","required":true,"description":"Advertiser id (`AR…`).","schema":{"type":"string","pattern":"^AR\\d+$"},"example":"AR01371945870127267841"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/brand":{"get":{"tags":["Brand"],"summary":"One-call brand dossier","description":"Runs several domain-keyed extractions in parallel and aggregates them into one response. Default parts: logo, estimated traffic, domain authority, Google ads, and the homepage as clean markdown (max 6 credits). Opt-in parts, requested explicitly via `parts=`: `organic` (organic keywords/traffic/rank), `backlinks` (backlink counts), `registration` (RDAP domain facts), `agent_ready` (llms.txt / agents.md / UCP probe) — 1 credit each. Each part succeeds or fails independently (`parts.<name>.ok`), so one blocked source never sinks the report. Credits = sum of successful, non-cached parts (cached parts are free). `markdown` is the combined report.\n\n**Credits: 6** (refunded on failure).","operationId":"getBrand","parameters":[{"name":"domain","in":"query","required":true,"description":"The brand domain to profile. Accepts a bare domain or a full URL.","schema":{"type":"string"},"example":"nike.com"},{"name":"parts","in":"query","required":false,"description":"Comma-separated parts. Default: logo, traffic, authority, ads, homepage. Opt-in extras: organic, backlinks, registration, agent_ready.","schema":{"type":"array","items":{"type":"string","enum":["logo","traffic","authority","ads","homepage","organic","backlinks","registration","agent_ready"]},"default":["logo","traffic","authority","ads","homepage"]},"example":"logo,traffic,authority"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandReport"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/brand/logo":{"get":{"tags":["Brand"],"summary":"Brand logo / favicon","description":"The domain's logo/favicon: a stable, hotlinkable image URL plus metadata (source, size, content type). The markdown output embeds the image. Logos are cached for 7 days — repeat lookups are free.\n\n**Credits: 1** (refunded on failure).","operationId":"getBrandLogo","parameters":[{"name":"domain","in":"query","required":true,"description":"The domain to fetch the logo for. Accepts a bare domain or a full URL.","schema":{"type":"string"},"example":"nike.com"},{"name":"size","in":"query","required":false,"description":"Requested image size in pixels (16–256, default 128).","schema":{"type":"integer","minimum":16,"maximum":256,"default":128}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/facebook/page":{"get":{"tags":["Social"],"summary":"Facebook page details","description":"Page name, category, followers/likes, website, phone/email/address when public, page id (usable with `/api/v1/ads/meta`), and whether the page is currently running ads.\n\nProvide exactly one of: `slug`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialFacebookPage","parameters":[{"name":"slug","in":"query","required":false,"description":"Facebook page slug, e.g. `nike` for facebook.com/nike.","schema":{"type":"string"},"example":"nike"},{"name":"url","in":"query","required":false,"description":"Full Facebook page URL (alternative to `slug`).","schema":{"type":"string","format":"uri"}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/instagram/profile":{"get":{"tags":["Social"],"summary":"Instagram profile","description":"Profile name, bio, follower/following counts, verification, category, website and bio links, read from the public profile with no login. Typical latency 3–8 s; retry on `provider_error` (credits are refunded automatically).\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialInstagramProfile","parameters":[{"name":"username","in":"query","required":true,"description":"Instagram handle, with or without the leading `@`.","schema":{"type":"string"},"example":"nike"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/tiktok/profile":{"get":{"tags":["Social"],"summary":"TikTok profile","description":"Profile display name, bio, verification, follower/following/like/video counts, and bio link.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialTiktokProfile","parameters":[{"name":"username","in":"query","required":true,"description":"TikTok handle, with or without the leading `@`.","schema":{"type":"string"},"example":"gymshark"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/linkedin/company":{"get":{"tags":["Social"],"summary":"LinkedIn company page","description":"Company name, tagline, description, website, industry, size bucket, headquarters, founding year, type, specialties, follower and employees-on-LinkedIn counts, address, logo, affiliated and similar pages, and up to 10 recent posts. Read from the public page LinkedIn shows search engines — no login or LinkedIn API access.\n\nProvide exactly one of: `slug`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialLinkedinCompany","parameters":[{"name":"slug","in":"query","required":false,"description":"The `/company/<slug>` part of the page URL, e.g. `stripe`. Provide this or `url`. Numeric company ids are not supported.","schema":{"type":"string"},"example":"stripe"},{"name":"url","in":"query","required":false,"description":"A `linkedin.com/company/<slug>` URL, in any locale subdomain.","schema":{"type":"string","format":"uri"},"example":"https://www.linkedin.com/company/stripe"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/linkedin/person":{"get":{"tags":["Social"],"summary":"LinkedIn public profile","description":"Public member profile: name, headline, location, about, follower and connection counts, badges, avatar, websites, current companies, experience, and education. `public_view` is `full` for members LinkedIn features (Creator / Top Voice) and `limited` for everyone else — then the headline and most experience/education entries are withheld. Profiles LinkedIn hides from logged-out visitors (nonexistent or public visibility off) return `not_found`.\n\nProvide exactly one of: `handle`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialLinkedinPerson","parameters":[{"name":"handle","in":"query","required":false,"description":"The `/in/<handle>` part of the profile URL, e.g. `williamhgates`. Provide this or `url`.","schema":{"type":"string"},"example":"williamhgates"},{"name":"url","in":"query","required":false,"description":"A `linkedin.com/in/<handle>` profile URL.","schema":{"type":"string","format":"uri"},"example":"https://www.linkedin.com/in/williamhgates"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/youtube/video":{"get":{"tags":["Social"],"summary":"YouTube video details","description":"Title, description, tags, category, duration, publish date, **exact** view and like counts, thumbnail, and the channel (name, handle, subscriber count). Pass a video id or any watch / youtu.be / Shorts URL.\n\nProvide exactly one of: `video_id`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialYoutubeVideo","parameters":[{"name":"video_id","in":"query","required":false,"description":"11-character YouTube video id. Provide this or `url`.","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{11}$"},"example":"dQw4w9WgXcQ"},{"name":"url","in":"query","required":false,"description":"A `youtube.com/watch?v=…`, `youtu.be/…`, or `youtube.com/shorts/…` URL.","schema":{"type":"string","format":"uri"},"example":"https://www.youtube.com/watch?v=dQw4w9WgXcQ"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/youtube/channel":{"get":{"tags":["Social"],"summary":"YouTube channel profile","description":"Channel title, description, country, join date, subscriber count, lifetime view count, video count, external links (socials, website), avatar, and banner.\n\nProvide exactly one of: `handle`, `channel_id`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialYoutubeChannel","parameters":[{"name":"handle","in":"query","required":false,"description":"Channel handle, with or without the leading `@`. Provide this, `channel_id`, or `url`.","schema":{"type":"string"},"example":"mkbhd"},{"name":"channel_id","in":"query","required":false,"description":"Channel id (`UC…`, 24 characters).","schema":{"type":"string","pattern":"^UC[A-Za-z0-9_-]{22}$"},"example":"UCBJycsmduvYEL83R_U4JriQ"},{"name":"url","in":"query","required":false,"description":"A `youtube.com/@handle`, `/channel/UC…`, `/c/…`, or `/user/…` URL.","schema":{"type":"string","format":"uri"},"example":"https://www.youtube.com/@mkbhd"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/youtube/transcript":{"get":{"tags":["Social"],"summary":"YouTube video transcript","description":"Full transcript of a video as clean prose paragraphs **and** timestamped blocks (markdown), with timed snippets and the joined text in `data`, plus the video metadata (title, channel, views, likes, publish date). Works for manual and auto-generated captions; falls back to English, then the first available track, and machine-translates into `lang` when no native track exists.\n\nProvide exactly one of: `video_id`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialYoutubeTranscript","parameters":[{"name":"video_id","in":"query","required":false,"description":"11-character YouTube video id. Provide this or `url`.","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{11}$"},"example":"dQw4w9WgXcQ"},{"name":"url","in":"query","required":false,"description":"A `youtube.com/watch?v=…`, `youtu.be/…`, or `youtube.com/shorts/…` URL.","schema":{"type":"string","format":"uri"},"example":"https://youtu.be/dQw4w9WgXcQ"},{"name":"lang","in":"query","required":false,"description":"Preferred caption language code (`en`, `ja`, `pt-BR`, …). Default: English, then the first available track.","schema":{"type":"string"},"example":"en"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/youtube/channel/videos":{"get":{"tags":["Social"],"summary":"YouTube channel videos","description":"A channel's uploads, 30 per page — title, view count, published-ago, and length — sorted latest, most popular, or oldest (YouTube's own tab sorts). See what a competitor posts and what performs; pair with `/social/youtube/video` for exact figures on any id.\n\nProvide exactly one of: `handle`, `channel_id`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialYoutubeChannelVideos","parameters":[{"name":"handle","in":"query","required":false,"description":"Channel handle, with or without the leading `@`. Provide this, `channel_id`, or `url`.","schema":{"type":"string"},"example":"mkbhd"},{"name":"channel_id","in":"query","required":false,"description":"Channel id (`UC…`, 24 characters).","schema":{"type":"string","pattern":"^UC[A-Za-z0-9_-]{22}$"},"example":"UCBJycsmduvYEL83R_U4JriQ"},{"name":"url","in":"query","required":false,"description":"A `youtube.com/@handle` (or `/channel/UC…`) URL.","schema":{"type":"string","format":"uri"},"example":"https://www.youtube.com/@mkbhd"},{"name":"sort","in":"query","required":false,"description":"`latest` (default), `popular`, or `oldest`.","schema":{"type":"string","enum":["latest","popular","oldest"],"default":"latest"},"example":"popular"},{"name":"max_pages","in":"query","required":false,"description":"Pages of 30 videos to fetch (1–5). Default 1.","schema":{"type":"integer","minimum":1,"maximum":5,"default":1},"example":2},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/youtube/search":{"get":{"tags":["Social"],"summary":"YouTube search","description":"YouTube search results — videos, Shorts, channels, and playlists in page order, with estimated total, per-result views / age / length / channel, and YouTube's own filters (type, upload date, duration, relevance vs popularity). Content and keyword research for video. Accepts the same query you would type into YouTube.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialYoutubeSearch","parameters":[{"name":"q","in":"query","required":true,"description":"Search query.","schema":{"type":"string"},"example":"best running shoes 2026"},{"name":"sort","in":"query","required":false,"description":"`relevance` (default) or `popularity`. YouTube web search no longer offers upload-date or rating sorts — use `upload_date` to restrict recency.","schema":{"type":"string","enum":["relevance","popularity"],"default":"relevance"},"example":"popularity"},{"name":"type","in":"query","required":false,"description":"Restrict to `video`, `shorts`, `channel`, `playlist`, or `movie`.","schema":{"type":"string","enum":["video","shorts","channel","playlist","movie"]},"example":"video"},{"name":"upload_date","in":"query","required":false,"description":"Uploaded within: `today`, `week`, `month`, or `year`.","schema":{"type":"string","enum":["today","week","month","year"]},"example":"month"},{"name":"duration","in":"query","required":false,"description":"`short` (< 3 min), `medium` (3–20 min), or `long` (> 20 min).","schema":{"type":"string","enum":["short","medium","long"]},"example":"medium"},{"name":"max_pages","in":"query","required":false,"description":"Result pages to fetch (1–5), ~20 items each. Default 1.","schema":{"type":"integer","minimum":1,"maximum":5,"default":1},"example":1},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/x/profile":{"get":{"tags":["Social"],"summary":"X (Twitter) profile","description":"X (formerly Twitter) profile: followers, following, post and media counts, bio, website, location, join date, verification type, and the \"based in\" country from X's About-this-account panel. No X API key or login. \"X\" and \"Twitter\" refer to the same platform throughout.\n\nProvide exactly one of: `handle`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialXProfile","parameters":[{"name":"handle","in":"query","required":false,"description":"X handle, with or without the leading `@`. Provide this or `url`.","schema":{"type":"string"},"example":"huel"},{"name":"url","in":"query","required":false,"description":"An `x.com/<handle>` or `twitter.com/<handle>` profile URL.","schema":{"type":"string","format":"uri"},"example":"https://x.com/huel"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/x/tweets":{"get":{"tags":["Social"],"summary":"X (Twitter) posts timeline","description":"One page (about 20) of an X (Twitter) account's posts, newest first, pinned post first — text, media, likes, reposts, replies, quotes, bookmarks, views, quoted posts, and reposts. Pass the returned `next_cursor` as `cursor` for the next page (each page is one credit).\n\nProvide exactly one of: `handle`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialXTweets","parameters":[{"name":"handle","in":"query","required":false,"description":"X handle, with or without the leading `@`. Provide this or `url`.","schema":{"type":"string"},"example":"huel"},{"name":"url","in":"query","required":false,"description":"An `x.com/<handle>` profile URL.","schema":{"type":"string","format":"uri"},"example":"https://x.com/huel"},{"name":"cursor","in":"query","required":false,"description":"`next_cursor` from the previous page.","schema":{"type":"string"}},{"name":"with_replies","in":"query","required":false,"description":"`true` to include the account's replies (the \"Posts & replies\" tab).","schema":{"type":"string","enum":["true","false"],"default":"false"},"example":"false"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/x/tweet":{"get":{"tags":["Social"],"summary":"X (Twitter) single post + thread","description":"One X (Twitter) post with full engagement counts, media, the quoted post if any, and the author's own unrolled thread (1/n, 2/n, …). X Articles (long-form posts) come with their full body as `article` (markdown, text, images) and are rendered in the markdown output. Accepts a post id or an `x.com/<handle>/status/<id>` URL.\n\nProvide exactly one of: `id`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialXTweet","parameters":[{"name":"id","in":"query","required":false,"description":"Numeric post id. Provide this or `url`.","schema":{"type":"string","pattern":"^\\d{1,25}$"},"example":"2080284119838204327"},{"name":"url","in":"query","required":false,"description":"An `x.com/<handle>/status/<id>` URL.","schema":{"type":"string","format":"uri"},"example":"https://x.com/huel/status/2080284119838204327"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/social/x/replies":{"get":{"tags":["Social"],"summary":"X (Twitter) replies to a post","description":"Replies from other users to an X (Twitter) post, as structured posts with author, engagement, and `replying_to` so you can rebuild the tree. The original post is included on the first page. Paginate with `next_cursor`. X hides some low-quality replies from logged-out viewers, so fewer replies than the post's reply count is normal.\n\nProvide exactly one of: `id`, `url`.\n\n**Credits: 1** (refunded on failure).","operationId":"getSocialXReplies","parameters":[{"name":"id","in":"query","required":false,"description":"Numeric post id. Provide this or `url`.","schema":{"type":"string","pattern":"^\\d{1,25}$"},"example":"2080284119838204327"},{"name":"url","in":"query","required":false,"description":"An `x.com/<handle>/status/<id>` URL.","schema":{"type":"string","format":"uri"},"example":"https://x.com/huel/status/2080284119838204327"},{"name":"cursor","in":"query","required":false,"description":"`next_cursor` from the previous page.","schema":{"type":"string"}},{"name":"ranking","in":"query","required":false,"description":"`relevance` (X's default ordering), `recency`, or `likes`.","schema":{"type":"string","enum":["relevance","recency","likes"],"default":"relevance"},"example":"recency"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/tiktok/shop/product":{"get":{"tags":["TikTok Shop"],"summary":"TikTok Shop product detail","description":"Product detail with **exact** figures: units sold, per-SKU stock and pricing, rating with the full 1–5 star histogram, categories, images, and a small review sample. Snapshot stock over time and diff it to estimate sales velocity. Region (prices/currency) follows the scraper exit IP.\n\n**Credits: 1** (refunded on failure).","operationId":"getTiktokShopProduct","parameters":[{"name":"product_id","in":"query","required":true,"description":"Numeric product id (~19 digits), from a `/view/product/<id>` or `/shop/pdp/<slug>/<id>` URL, or from the store/category endpoints.","schema":{"type":"string","pattern":"^\\d+$"},"example":"1729587769570529799"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/tiktok/shop/product/videos":{"get":{"tags":["TikTok Shop"],"summary":"Videos promoting a TikTok Shop product","description":"TikTok videos promoting a product (up to ~10 — TikTok caps this feed): creator, play and like counts, upload date, and video links. Pair with the product endpoint (units sold) to attribute a product’s sales to the creators and videos driving them.\n\n**Credits: 1** (refunded on failure).","operationId":"getTiktokShopProductVideos","parameters":[{"name":"product_id","in":"query","required":true,"description":"Numeric product id (~19 digits).","schema":{"type":"string","pattern":"^\\d+$"},"example":"1729587769570529799"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/tiktok/shop/seller":{"get":{"tags":["TikTok Shop"],"summary":"TikTok Shop seller summary","description":"Shop summary by seller id: name, region, rating, items sold, followers, product and review counts. A lightweight lookup — use `/api/v1/tiktok/shop/store` when you also want the product catalog. Get the `seller_id` from a product’s detail response.\n\n**Credits: 1** (refunded on failure).","operationId":"getTiktokShopSeller","parameters":[{"name":"seller_id","in":"query","required":true,"description":"Numeric seller/store id (~19 digits).","schema":{"type":"string","pattern":"^\\d+$"},"example":"7495794203056835079"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/tiktok/shop/store":{"get":{"tags":["TikTok Shop"],"summary":"TikTok Shop store catalog","description":"Store info plus the product catalog (~30 products per page, with sold counts, ratings, and prices). The bulk-discovery path: walk a seller’s full catalog here, then feed `product_id`s into `/api/v1/tiktok/shop/product` for per-product detail. `has_more: true` means more pages exist than `max_pages` fetched.\n\n**Credits: 2** (refunded on failure).","operationId":"getTiktokShopStore","parameters":[{"name":"seller_id","in":"query","required":true,"description":"Numeric seller/store id (~19 digits).","schema":{"type":"string","pattern":"^\\d+$"},"example":"7495794203056835079"},{"name":"max_pages","in":"query","required":false,"description":"Catalog pages of ~30 products to fetch (1–10, default 1).","schema":{"type":"integer","minimum":1,"maximum":10,"default":1}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/tiktok/shop/category":{"get":{"tags":["TikTok Shop"],"summary":"TikTok Shop category listing","description":"Category info, child categories (walk `children[]` recursively to enumerate the tree), and the top ~15 products. Deeper category pagination is not exposed upstream — use the store endpoint for exhaustive per-seller catalogs; use categories for top-of-category sampling and tree discovery.\n\n**Credits: 1** (refunded on failure).","operationId":"getTiktokShopCategory","parameters":[{"name":"category_id","in":"query","required":true,"description":"Numeric category id, e.g. `700645` (Health). Get child ids from this endpoint’s `children[]` or a product’s `categories[]`.","schema":{"type":"string","pattern":"^\\d+$"},"example":"700645"},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/shopify/categories":{"get":{"tags":["Shopify"],"summary":"Shopify store catalogue categories","description":"What a Shopify store sells, in Shopify's standard product taxonomy: the primary category, vertical, and top categories with product counts, from the store's public storefront catalogue (250 products per page). Works for any store on Shopify — no store credentials. Headless or non-Shopify hosts return an empty result.\n\n**Credits: 1** (refunded on failure).","operationId":"getShopifyCategories","parameters":[{"name":"domain","in":"query","required":true,"description":"Store domain, e.g. `allbirds.com`. Accepts a bare domain or a full URL.","schema":{"type":"string"},"example":"nike.com"},{"name":"max_pages","in":"query","required":false,"description":"Pages of 250 products to scan (1–8). Default 4.","schema":{"type":"integer","minimum":1,"maximum":8,"default":4},"example":4},{"name":"per_product","in":"query","required":false,"description":"`true` to also return every product with its category.","schema":{"type":"string","enum":["true","false"],"default":"false"}},{"name":"format","in":"query","required":false,"description":"Response shape: \"json\" (structured data only), \"markdown\" (markdown only), or \"both\".","schema":{"type":"string","enum":["json","markdown","both"],"default":"both"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Extraction/conversion failed — credits refunded. `code` carries the failure category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/conversions/{id}":{"get":{"tags":["Conversions"],"summary":"Fetch a past conversion or extraction","description":"Returns a conversion owned by the API key’s user, including its stored markdown and — for extractions — the structured `data` payload. Free (no credits charged).\n\n**Credits: free.**","operationId":"getConversionsId","parameters":[{"name":"id","in":"path","required":true,"description":"Conversion id returned by a convert/extraction call.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionDetail"}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (60 requests/min per key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key from /settings/apikeys."},"apiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"API key from /settings/apikeys (alternative header)."}},"schemas":{"ExtractionResult":{"type":"object","description":"A completed extraction. `data` is omitted when format=markdown; `markdown` is omitted when format=json.","properties":{"id":{"type":"string"},"status":{"type":"string","const":"completed"},"extractor":{"type":"string","description":"Extractor name, e.g. \"traffic\", \"meta-ads\", \"instagram-profile\"."},"title":{"type":["string","null"]},"sourceUrl":{"type":["string","null"],"description":"Canonical public URL of the extracted source."},"creditsCharged":{"type":"integer","description":"0 when served from the shared cache."},"cached":{"type":"boolean","description":"True when served from the shared extraction cache (free)."},"createdAt":{"type":"integer","description":"Unix epoch milliseconds."},"data":{"description":"Raw structured payload from the source.","type":["object","array","null"]},"markdown":{"type":"string","description":"Clean markdown rendering of the payload."}},"required":["id","status","extractor","creditsCharged","createdAt"]},"ConvertResult":{"type":"object","description":"A completed markdown conversion.","properties":{"id":{"type":"string"},"status":{"type":"string","const":"completed"},"title":{"type":["string","null"]},"sourceType":{"type":"string","enum":["url","file"]},"sourceUrl":{"type":["string","null"]},"provider":{"type":"string","description":"Conversion engine: \"jina\", \"cloudflare\", or \"tools-api\"."},"extractor":{"type":"string","description":"Present when the URL routed through a structured extractor."},"markdown":{"type":"string"},"data":{"description":"Raw structured payload (present when an extractor claimed the URL).","type":["object","array"]},"contentChars":{"type":"integer"},"creditsCharged":{"type":"integer"},"createdAt":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","status","sourceType","provider","markdown","creditsCharged","createdAt"]},"ConversionDetail":{"type":"object","description":"A stored conversion or extraction.","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["completed","failed"]},"sourceType":{"type":"string","enum":["url","file"]},"sourceUrl":{"type":["string","null"]},"title":{"type":["string","null"]},"provider":{"type":"string"},"extractor":{"type":"string"},"contentChars":{"type":"integer"},"creditsUsed":{"type":"integer"},"errorMessage":{"type":"string"},"createdAt":{"type":"integer"},"completedAt":{"type":"integer"},"markdown":{"type":["string","null"]},"data":{"description":"Structured payload (extractions only).","type":["object","array"]}},"required":["id","status","sourceType","provider","createdAt"]},"BrandReport":{"type":"object","description":"Aggregated brand dossier. Each part succeeds or fails independently; `markdown` is the combined report (omitted when format=json).","properties":{"domain":{"type":"string"},"creditsCharged":{"type":"integer","description":"Sum across successful, non-cached parts."},"parts":{"type":"object","description":"Keyed by part name (logo, traffic, authority, ads, homepage).","additionalProperties":{"oneOf":[{"type":"object","properties":{"ok":{"type":"boolean","const":true},"id":{"type":"string"},"title":{"type":["string","null"]},"creditsCharged":{"type":"integer"},"cached":{"type":"boolean"},"data":{"type":["object","array","null"]},"markdown":{"type":"string"}},"required":["ok","id","creditsCharged"]},{"type":"object","properties":{"ok":{"type":"boolean","const":false},"error":{"type":"string"},"code":{"type":"string"}},"required":["ok","error","code"]}]}},"markdown":{"type":"string","description":"Combined brand report markdown."}},"required":["domain","creditsCharged","parts"]},"Error":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable message."},"code":{"type":"string","description":"Stable error code, e.g. \"invalid_params\", \"insufficient_credits\", \"provider_error\"."}},"required":["error","code"]}}}}