{"openapi": "3.1.0", "info": {"title": "GEO Audit API", "version": "1.0.0", "description": "GEO Audit renders 1-5 URLs (or HTML captured in the browser) in a real browser, compares them with the pre-JS HTML and scores SEO, AEO and GEO items with rules. Only the main content (without navigation, footer and recommendation widgets) is judged, and a re-review step drops weakly supported findings. With a topic keyword it checks coverage against ListeningMind Data API search volume, intents and related keywords. Marketers and SEO staff use it for pages in Korea, Japan and the US. Workflow: get_queue_status → start_audit → get_audit → download_report_pdf → download_report_html → rerun_audit → list_history → delete_history_entry", "contact": {"email": "m-support@listeningmind.com"}}, "servers": [{"url": "https://daas-geo.listeningmind.ai"}], "paths": {"/api/queue": {"get": {"operationId": "get_queue_status", "summary": "Get queue status", "description": "Shows how busy the audit queue is before submitting: {running, waiting, slots, avg_s}. avg_s is the recent average audit duration in seconds. Read only, free. Usually followed by: start_audit.", "tags": ["read"], "x-lm-kind": "read", "x-lm-cost": "free", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}}}, "/api/audit": {"post": {"operationId": "start_audit", "summary": "Start URL audit", "description": "Starts an SEO/AEO/GEO audit of 1-5 public URLs. Each page is rendered in a headless browser, compared with the pre-JS HTML, checked against rule-based items, then re-reviewed. Returns the job status object {id, state (queued, running), urls, progress[], position, ahead, eta_s}. Poll get_audit at least once a minute: a queued job that is not polled for about 90 seconds is dropped. One active audit per client IP; 429 returns the running job_id. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: Data API credits when topic is set (keyword_info + intent_finder, cached 24 h per member: own cache free, others' at full price) plus LLM review tokens converted to credits (USD 1 = 1,000 credits); reported as credits.spent in the result. Time: limit 240 seconds per job (40 seconds per page fetch). Usually followed by: get_audit.", "tags": ["run"], "x-lm-kind": "run", "x-lm-cost": "Data API credits when topic is set (keyword_info + intent_finder, cached 24 h per member: own cache free, others' at full price) plus LLM review tokens converted to credits (USD 1 = 1,000 credits); reported as credits.spent in the result", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"urls": {"type": "array", "description": "1-5 public page URLs (http or https), audited together; duplicates are removed. Pages in the same job are compared with each other (duplicate titles and descriptions).", "items": {"type": "string"}, "minItems": 1, "maxItems": 5}, "topic": {"type": "string", "description": "Optional topic keyword (max 60 characters). When set, ListeningMind search volume, competition, intents and up to 25 related keywords are fetched and each report gets a topic coverage section. Blank = no topic section and no credits.", "maxLength": 60}, "gl": {"type": "string", "description": "Market for the topic search data: kr, jp or us. Default kr. Has no effect when topic is empty.", "enum": ["kr", "jp", "us"], "default": "kr"}, "parent": {"type": "string", "description": "Optional id of an earlier audit to compare against; the reports then include compare (score and item changes). Without it the previous audit of the same URL by the same owner is used when one exists."}}, "required": ["urls"]}}}}}}, "/api/audit_html": {"post": {"operationId": "start_audit_html", "summary": "Start audit from HTML", "description": "Audits one page from rendered HTML captured in the user's browser (what the bookmarklet and Chrome extension send), for pages behind login, bot blocking or on a private network. The server does not fetch private hosts. Returns the job status object; poll get_audit. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: Data API credits when topic is set (keyword_info + intent_finder, cached 24 h per member: own cache free, others' at full price) plus LLM review tokens converted to credits (USD 1 = 1,000 credits); reported as credits.spent in the result. Time: limit 240 seconds. Usually followed by: get_audit.", "tags": ["run"], "x-lm-kind": "run", "x-lm-cost": "Data API credits when topic is set (keyword_info + intent_finder, cached 24 h per member: own cache free, others' at full price) plus LLM review tokens converted to credits (USD 1 = 1,000 credits); reported as credits.spent in the result", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"url": {"type": "string", "description": "URL of the captured page (max 2048 characters)."}, "html": {"type": "string", "description": "Rendered HTML of the page, 20 characters to 6 MB."}, "source": {"type": "string", "description": "Where the HTML came from; stored with the audit and shown in the report. Does not change scoring.", "enum": ["bookmarklet", "extension"], "default": "extension"}, "topic": {"type": "string", "description": "Optional topic keyword (max 60 characters). When set, ListeningMind search volume, competition, intents and up to 25 related keywords are fetched and each report gets a topic coverage section. Blank = no topic section and no credits.", "maxLength": 60}, "gl": {"type": "string", "description": "Market for the topic search data: kr, jp or us. Default kr. Has no effect when topic is empty.", "enum": ["kr", "jp", "us"], "default": "kr"}, "parent": {"type": "string", "description": "Optional id of an earlier audit to compare against; the reports then include compare (score and item changes). Without it the previous audit of the same URL by the same owner is used when one exists."}}, "required": ["url", "html"]}}}}}}, "/api/audit/{jid}": {"get": {"operationId": "get_audit", "summary": "Get audit status and result", "description": "Reads one audit. While queued or running returns {id, state, urls, progress[] (per-URL stage), position, ahead, eta_s or elapsed_s}; when done returns state done and result {reports[{url, final_url, facts, fetch, render_compare, scores{axes, overall, grade}, readability, items[], review, topic, compare}], topic, axes_meta, cats_meta, generated_at, job}. Repeat until state is done, error or cancelled. Read only, free. Waits up to about 45 s for 'state' to reach done, error, cancelled; call again if not done. Usually followed by: download_report_pdf, download_report_html, rerun_audit.", "tags": ["read"], "x-lm-kind": "read", "x-lm-cost": "free", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "parameters": [{"name": "jid", "in": "path", "required": true, "description": "Audit id returned by start_audit, start_audit_html or rerun_audit (10-40 characters: letters, digits, _ or -).", "schema": {"type": "string"}}]}, "delete": {"operationId": "cancel_audit", "summary": "Cancel audit", "description": "Cancels a queued audit (a running one finishes). Returns {state}. 404 when the job is no longer in memory. Changes saved data in the app; no credits.", "tags": ["action"], "x-lm-kind": "action", "x-lm-cost": "free", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "parameters": [{"name": "jid", "in": "path", "required": true, "description": "Audit id returned by start_audit, start_audit_html or rerun_audit (10-40 characters: letters, digits, _ or -).", "schema": {"type": "string"}}]}}, "/api/audit/{jid}/rerun": {"post": {"operationId": "rerun_audit", "summary": "Re-run audit for comparison", "description": "Audits the same URLs again and links the new audit to this one so the report shows what changed. Not possible for private-network pages (use start_audit_html with parent instead). Returns the new job status object; poll get_audit with its id. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: Data API credits when topic is set (keyword_info + intent_finder, cached 24 h per member: own cache free, others' at full price) plus LLM review tokens converted to credits (USD 1 = 1,000 credits); reported as credits.spent in the result. Usually followed by: get_audit.", "tags": ["run"], "x-lm-kind": "run", "x-lm-cost": "Data API credits when topic is set (keyword_info + intent_finder, cached 24 h per member: own cache free, others' at full price) plus LLM review tokens converted to credits (USD 1 = 1,000 credits); reported as credits.spent in the result", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "parameters": [{"name": "jid", "in": "path", "required": true, "description": "Audit id returned by start_audit, start_audit_html or rerun_audit (10-40 characters: letters, digits, _ or -).", "schema": {"type": "string"}}]}}, "/api/audit/{jid}/report.pdf": {"get": {"operationId": "download_report_pdf", "summary": "Download PDF report", "description": "Downloads the finished audit report as a PDF (rendered from /report/{jid}). Limited to 60 downloads per hour per IP. Read only, free.", "tags": ["read"], "x-lm-kind": "read", "x-lm-cost": "free", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "parameters": [{"name": "jid", "in": "path", "required": true, "description": "Audit id returned by start_audit, start_audit_html or rerun_audit (10-40 characters: letters, digits, _ or -).", "schema": {"type": "string"}}]}}, "/api/audit/{jid}/report.html": {"get": {"operationId": "download_report_html", "summary": "Download HTML report", "description": "Downloads the finished audit report as a single static HTML file with inlined CSS. Limited to 60 downloads per hour per IP. Read only, free.", "tags": ["read"], "x-lm-kind": "read", "x-lm-cost": "free", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "parameters": [{"name": "jid", "in": "path", "required": true, "description": "Audit id returned by start_audit, start_audit_html or rerun_audit (10-40 characters: letters, digits, _ or -).", "schema": {"type": "string"}}]}}, "/api/history": {"get": {"operationId": "list_history", "summary": "List audit history", "description": "Lists past audits of the caller: {items[{id, created, owner, source, urls, topic, parent, ...}]}, newest first, up to 200. Only audits submitted with the same X-GA-Owner header are returned; without that header the list is empty. Read only, free. Usually followed by: get_audit.", "tags": ["read"], "x-lm-kind": "read", "x-lm-cost": "free", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}}}, "/api/history/{jid}": {"delete": {"operationId": "delete_history_entry", "summary": "Delete history entry", "description": "Deletes one stored audit result. Works only for audits owned by the X-GA-Owner token sent with the request. Returns {deleted: true} or 404. Deletes data. A person approves it first.", "tags": ["delete"], "x-lm-kind": "delete", "x-lm-cost": "free", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "parameters": [{"name": "jid", "in": "path", "required": true, "description": "Audit id returned by start_audit, start_audit_html or rerun_audit (10-40 characters: letters, digits, _ or -).", "schema": {"type": "string"}}]}}}, "externalDocs": {"url": "https://daas-geo.listeningmind.ai/agents.md", "description": "Agent guide"}}