{"openapi": "3.1.0", "info": {"title": "Prompt Builder API", "version": "1.0.0", "description": "From a brand or category keyword it collects ListeningMind related keywords, People Also Ask questions and Google AI Overviews, extracts CEP, nano context, KBF, constraints, avoidance, reasons to believe and competitors, and generates managed prompts in 6 fixed groups with estimated monthly prompt volume. It can then ask ChatGPT and Gemini those prompts to measure brand visibility, and keeps history and Excel exports. Used by GEO leads and brand managers. Markets: Korea, Japan, US. Workflow: preview_detection → start_analysis → get_job_status → get_run → start_visibility → get_visibility_status → get_visibility → export_prompts_xlsx → list_history", "contact": {"email": "m-support@listeningmind.com"}}, "servers": [{"url": "https://daas-prompt.listeningmind.ai"}], "paths": {"/confirm": {"get": {"operationId": "preview_detection", "summary": "Preview auto-detection (confirm step)", "description": "The 'AI helper' step the UI shows before a run: resolves the keyword's meaning, may switch an ambiguous or low-data brand keyword to its category, gathers related keywords and detects own brand, competitors and exclude words. Returns an HTML form pre-filled with collect keyword, focus, own, comp, exclude, gl, n, max; pass those values to start_analysis. 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: 1 LLM call for sense resolution plus ListeningMind finder calls (path, intent, cluster) for the keyword. Time: 10-40 seconds. Usually followed by: start_analysis.", "tags": ["run"], "x-lm-kind": "run", "x-lm-cost": "1 LLM call for sense resolution plus ListeningMind finder calls (path, intent, cluster) for the keyword", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "parameters": [{"name": "q", "in": "query", "required": true, "description": "Brand or category keyword to analyze; related keywords, questions and SERPs are collected around it. An ambiguous or low-data brand may be switched to its category automatically (the brand is then kept as own brand).", "schema": {"type": "string"}}, {"name": "gl", "in": "query", "required": false, "description": "Market. Default follows the UI language (ja -> jp, en -> us, else kr).", "schema": {"type": "string", "enum": ["kr", "jp", "us"]}}, {"name": "focus", "in": "query", "required": false, "description": "Optional topic that fixes the meaning of the keyword, e.g. a category for an ambiguous brand. Also steers which related keywords and prompts are kept.", "schema": {"type": "string", "maxLength": 60}}, {"name": "n", "in": "query", "required": false, "description": "Requested number of managed prompts. The app makes round(n/3) scenarios, clamped to 3-100, so values above 300 act as 300. UI start page offers 72, 90, 120, 180, 300 (72 preselected); the confirm page allows 6-300 in steps of 6. Server default when omitted: 24.", "schema": {"type": "integer", "default": 72, "minimum": 6, "maximum": 300}}, {"name": "max", "in": "query", "required": false, "description": "How many related keywords are queried for SERP, People Also Ask and AI Overview. More keywords give more questions and evidence and cost more credits.", "schema": {"type": "integer", "default": 15, "minimum": 3, "maximum": 40}}, {"name": "prefilter", "in": "query", "required": false, "description": "'1' (default) queries only related keywords that have People Also Ask questions; '0' queries keywords without that filter. Accepted true values: 1, true, on, yes.", "schema": {"type": "string", "enum": ["1", "0"], "default": "1"}}, {"name": "own", "in": "query", "required": false, "description": "Own brand names, comma separated (from the confirm step). Drives brand vs non-brand prompt split and visibility scoring. If own and comp are both given the server may move names between them.", "schema": {"type": "string", "maxLength": 200}}, {"name": "comp", "in": "query", "required": false, "description": "Competitor brand names, comma separated. Used in comparison prompts and visibility scoring.", "schema": {"type": "string", "maxLength": 200}}, {"name": "exclude", "in": "query", "required": false, "description": "Words to exclude (other meanings, noise), comma or newline separated; phrases are split into words, words of q and own brands are protected.", "schema": {"type": "string", "maxLength": 300}}, {"name": "ui", "in": "query", "required": false, "description": "Page and label language only (result content language follows gl).", "schema": {"type": "string", "enum": ["ko", "ja", "en"]}}, {"name": "orig", "in": "query", "required": false, "description": "Original keyword when the user edited it on the confirm page.", "schema": {"type": "string"}}]}}, "/": {"get": {"operationId": "start_analysis", "summary": "Start analysis", "description": "Starts a full run in the background (pass run='1'; without it the address only prefills the form): collects related keywords, People Also Ask and AI Overview from ListeningMind, analyzes CEP, nano intent, KBF, constraints, avoidance and competitors, generates managed prompts in 6 fixed groups, estimates monthly prompt volume and fills demand gaps, then saves the run to history. Returns the HTML progress page; the job id is in its poll script (var JID=\"<12 hex>\"). Poll get_job_status with that 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: ListeningMind Data API credits for finder and SERP calls (up to max keywords) plus paid LLM calls: recent runs about 6,400-7,500 credits (about 85-100 Lima), reported as credits.spent. Time: about 1-4 minutes. Usually followed by: get_job_status.", "tags": ["run"], "x-lm-kind": "run", "x-lm-cost": "ListeningMind Data API credits for finder and SERP calls (up to max keywords) plus paid LLM calls: recent runs about 6,400-7,500 credits (about 85-100 Lima), reported as credits.spent", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "parameters": [{"name": "q", "in": "query", "required": true, "description": "Brand or category keyword to analyze; related keywords, questions and SERPs are collected around it. An ambiguous or low-data brand may be switched to its category automatically (the brand is then kept as own brand).", "schema": {"type": "string"}}, {"name": "gl", "in": "query", "required": false, "description": "Market. Default follows the UI language (ja -> jp, en -> us, else kr).", "schema": {"type": "string", "enum": ["kr", "jp", "us"]}}, {"name": "focus", "in": "query", "required": false, "description": "Optional topic that fixes the meaning of the keyword, e.g. a category for an ambiguous brand. Also steers which related keywords and prompts are kept.", "schema": {"type": "string", "maxLength": 60}}, {"name": "n", "in": "query", "required": false, "description": "Requested number of managed prompts. The app makes round(n/3) scenarios, clamped to 3-100, so values above 300 act as 300. UI start page offers 72, 90, 120, 180, 300 (72 preselected); the confirm page allows 6-300 in steps of 6. Server default when omitted: 24.", "schema": {"type": "integer", "default": 72, "minimum": 6, "maximum": 300}}, {"name": "max", "in": "query", "required": false, "description": "How many related keywords are queried for SERP, People Also Ask and AI Overview. More keywords give more questions and evidence and cost more credits.", "schema": {"type": "integer", "default": 15, "minimum": 3, "maximum": 40}}, {"name": "prefilter", "in": "query", "required": false, "description": "'1' (default) queries only related keywords that have People Also Ask questions; '0' queries keywords without that filter. Accepted true values: 1, true, on, yes.", "schema": {"type": "string", "enum": ["1", "0"], "default": "1"}}, {"name": "own", "in": "query", "required": false, "description": "Own brand names, comma separated (from the confirm step). Drives brand vs non-brand prompt split and visibility scoring. If own and comp are both given the server may move names between them.", "schema": {"type": "string", "maxLength": 200}}, {"name": "comp", "in": "query", "required": false, "description": "Competitor brand names, comma separated. Used in comparison prompts and visibility scoring.", "schema": {"type": "string", "maxLength": 200}}, {"name": "exclude", "in": "query", "required": false, "description": "Words to exclude (other meanings, noise), comma or newline separated; phrases are split into words, words of q and own brands are protected.", "schema": {"type": "string", "maxLength": 300}}, {"name": "eng", "in": "query", "required": false, "description": "LLM engine for analysis and prompt generation: mix (Gemini and ChatGPT share work and cross-check), gemini or chatgpt. Falls back to an available engine when a key is missing. Server default mix.", "schema": {"type": "string", "enum": ["mix", "gemini", "chatgpt"], "default": "mix"}}, {"name": "ui", "in": "query", "required": false, "description": "Page and label language only (result content language follows gl).", "schema": {"type": "string", "enum": ["ko", "ja", "en"]}}, {"name": "run", "in": "query", "required": true, "description": "Must be '1': an explicit start. GET / with q but without run=1 only prefills the form (opening a shared or bookmarked address never starts a paid run).", "schema": {"type": "string", "enum": ["1"]}}]}}, "/api/status": {"get": {"operationId": "get_job_status", "summary": "Check run progress", "description": "Returns {status (running, done, error), stage, stage_label, elapsed, error, suggest}. suggest lists alternative keywords that have data when the keyword returned nothing. Repeat until done or error. A finished run that is no longer in memory still answers done. Read only, free. Waits up to about 45 s for 'status' to reach done, error; call again if not done. Usually followed by: get_run, get_result_html.", "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": "id", "in": "query", "required": true, "description": "Run id (12 hex chars), the job id shown by start_analysis.", "schema": {"type": "string"}}, {"name": "ui", "in": "query", "required": false, "description": "Page language.", "schema": {"type": "string", "enum": ["ko", "ja", "en"]}}]}}, "/api/run": {"get": {"operationId": "get_run", "summary": "Get run result (JSON)", "description": "Returns a saved run as structured JSON: {id, brand, gl, created_at, input, counts (related keywords, keywords queried, questions, AI overview items, scenarios, prompts), pkg (collected data: related keywords, journeys, aggregated questions, SERP text), ins (insight: brands, CEP, contexts, KBF, constraints, thresholds, avoidance, RTB, competitors, scenarios with prompts, estimated prompt volume _pv)}. 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": "id", "in": "query", "required": true, "description": "Run id (12 hex chars), the job id shown by start_analysis.", "schema": {"type": "string"}}]}}, "/api/result": {"get": {"operationId": "get_result_html", "summary": "Get result HTML fragment", "description": "Returns the rendered result section (insight cards, prompt tables, visibility card) as an HTML fragment, as the UI inserts it after the run. Answers 202 'not ready' while running. 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": "id", "in": "query", "required": true, "description": "Run id (12 hex chars), the job id shown by start_analysis.", "schema": {"type": "string"}}, {"name": "ui", "in": "query", "required": false, "description": "Page language.", "schema": {"type": "string", "enum": ["ko", "ja", "en"]}}]}}, "/api/vis/start": {"get": {"operationId": "start_visibility", "summary": "Start AI visibility measurement", "description": "Asks ChatGPT and Gemini (with web search) every managed prompt of a saved run 3 times and records whether the own brand and competitors appear, are recommended and which sources are cited. Returns {status, done, total}. Poll get_visibility_status. 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: paid LLM calls with web search = prompts x engines x 3 (e.g. 80 prompts x 2 x 3 = 480). Time: several minutes (about calls / 10 x 9 seconds). Usually followed by: get_visibility_status.", "tags": ["run"], "x-lm-kind": "run", "x-lm-cost": "paid LLM calls with web search = prompts x engines x 3 (e.g. 80 prompts x 2 x 3 = 480)", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "parameters": [{"name": "id", "in": "query", "required": true, "description": "Run id (12 hex chars), the job id shown by start_analysis.", "schema": {"type": "string"}}]}}, "/api/vis/status": {"get": {"operationId": "get_visibility_status", "summary": "Check visibility progress", "description": "Returns {status (running, done, error, none), done, total, error}. none means not measured and not running. Repeat until done or error. Read only, free. Waits up to about 45 s for 'status' to reach done, error, none; call again if not done. Usually followed by: get_visibility.", "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": "id", "in": "query", "required": true, "description": "Run id (12 hex chars), the job id shown by start_analysis.", "schema": {"type": "string"}}]}}, "/api/vis": {"get": {"operationId": "get_visibility", "summary": "Get visibility results", "description": "Returns the stored visibility measurement for a run: {engines, models, runs, per_prompt (answers per prompt and engine with brand mentions), kpi, opportunities, sources (cited domains), failed, created_at}. 404 {error:'not measured'} before measuring. 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": "id", "in": "query", "required": true, "description": "Run id (12 hex chars), the job id shown by start_analysis.", "schema": {"type": "string"}}]}}, "/export": {"get": {"operationId": "export_prompts_xlsx", "summary": "Download Excel", "description": "Downloads the managed prompts of a run as an .xlsx file: one row per prompt with group, brand type (non-brand, brand, comparison), prompt, interest intensity index (0-100), tier, question share, estimated monthly prompt count and range, confidence, trend, evidence keywords with volume, demand share, co-occurring words, gap-fill mark, topic, scenario, CEP, constraints, required KBF, avoidance, output format; plus visibility results when measured. 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": "id", "in": "query", "required": true, "description": "Run id (12 hex chars), the job id shown by start_analysis.", "schema": {"type": "string"}}]}}, "/history": {"get": {"operationId": "list_history", "summary": "List history", "description": "Returns the history page (HTML) listing saved runs for a market with time, keyword, focus and links to view (/history/view?id=), Excel export and delete. mk filters by market (kr, jp, us, all); default is the UI language's market. Read only, free. Usually followed by: get_run.", "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": "mk", "in": "query", "required": false, "description": "Market filter.", "schema": {"type": "string", "enum": ["kr", "jp", "us", "all"]}}, {"name": "ui", "in": "query", "required": false, "description": "Page language.", "schema": {"type": "string", "enum": ["ko", "ja", "en"]}}]}}, "/history/view": {"get": {"operationId": "view_saved_run", "summary": "View saved run page", "description": "Returns the full HTML result page of a saved run. 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": "id", "in": "query", "required": true, "description": "Run id (12 hex chars), the job id shown by start_analysis.", "schema": {"type": "string"}}, {"name": "ui", "in": "query", "required": false, "description": "Page language.", "schema": {"type": "string", "enum": ["ko", "ja", "en"]}}]}}, "/history/delete": {"post": {"operationId": "delete_run", "summary": "Delete a run", "description": "Deletes one of your saved runs (POST, form or JSON body {id, back}). Signed-in members only, and only the member who ran it: 401 signed out, 403 for another member's run. A form post is answered with 303 to the back path, JSON with {ok, id}. GET is refused (405). 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)"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"id": {"type": "string", "description": "Run id (12 hex chars), the job id shown by start_analysis."}, "back": {"type": "string", "description": "Path to redirect to after deleting (must start with /).", "default": "/history"}}, "required": ["id"]}}}}}}, "/api/collect": {"get": {"operationId": "collect_data", "summary": "Collect data only (JSON)", "description": "Collects the ListeningMind data package for a keyword (related keywords from path, intent and cluster finders, journeys, People Also Ask, AI Overview and SERP text) without LLM synthesis and without saving to history. For agents that write their own prompts. Returns the pkg JSON; 503 if the data API is unreachable. 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: ListeningMind Data API credits for finder calls plus SERP for up to max keywords. Time: about 20-90 seconds.", "tags": ["run"], "x-lm-kind": "run", "x-lm-cost": "ListeningMind Data API credits for finder calls plus SERP for up to max keywords", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "parameters": [{"name": "q", "in": "query", "required": true, "description": "Brand or category keyword to analyze; related keywords, questions and SERPs are collected around it. An ambiguous or low-data brand may be switched to its category automatically (the brand is then kept as own brand).", "schema": {"type": "string"}}, {"name": "gl", "in": "query", "required": false, "description": "Market. Default follows the UI language (ja -> jp, en -> us, else kr).", "schema": {"type": "string", "enum": ["kr", "jp", "us"]}}, {"name": "max", "in": "query", "required": false, "description": "How many related keywords are queried for SERP, People Also Ask and AI Overview. More keywords give more questions and evidence and cost more credits.", "schema": {"type": "integer", "default": 15, "minimum": 3, "maximum": 40}}, {"name": "prefilter", "in": "query", "required": false, "description": "'1' (default) queries only related keywords that have People Also Ask questions; '0' queries keywords without that filter. Accepted true values: 1, true, on, yes.", "schema": {"type": "string", "enum": ["1", "0"], "default": "1"}}, {"name": "focus", "in": "query", "required": false, "description": "Optional topic that fixes the meaning of the keyword, e.g. a category for an ambiguous brand. Also steers which related keywords and prompts are kept.", "schema": {"type": "string", "maxLength": 60}}]}}, "/api": {"get": {"operationId": "run_sync_analysis", "summary": "Run synchronous analysis (JSON, not saved)", "description": "Runs collection and insight synthesis in one blocking request and returns {insight, data}. Not saved to history and no job id, so it cannot be exported or measured later; use start_analysis for that. 422 when the keyword has no ListeningMind data. 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: ListeningMind Data API credits plus many paid LLM calls. Time: about 1-2 minutes or more.", "tags": ["run"], "x-lm-kind": "run", "x-lm-cost": "ListeningMind Data API credits plus many paid LLM calls", "responses": {"200": {"description": "Success"}, "default": {"description": "Error (application/problem+json or JSON with detail)"}}, "parameters": [{"name": "q", "in": "query", "required": true, "description": "Brand or category keyword to analyze; related keywords, questions and SERPs are collected around it. An ambiguous or low-data brand may be switched to its category automatically (the brand is then kept as own brand).", "schema": {"type": "string"}}, {"name": "gl", "in": "query", "required": false, "description": "Market. Default follows the UI language (ja -> jp, en -> us, else kr).", "schema": {"type": "string", "enum": ["kr", "jp", "us"]}}, {"name": "max", "in": "query", "required": false, "description": "How many related keywords are queried for SERP, People Also Ask and AI Overview. More keywords give more questions and evidence and cost more credits.", "schema": {"type": "integer", "default": 15, "minimum": 3, "maximum": 40}}, {"name": "prefilter", "in": "query", "required": false, "description": "'1' (default) queries only related keywords that have People Also Ask questions; '0' queries keywords without that filter. Accepted true values: 1, true, on, yes.", "schema": {"type": "string", "enum": ["1", "0"], "default": "1"}}, {"name": "focus", "in": "query", "required": false, "description": "Optional topic that fixes the meaning of the keyword, e.g. a category for an ambiguous brand. Also steers which related keywords and prompts are kept.", "schema": {"type": "string", "maxLength": 60}}, {"name": "n", "in": "query", "required": false, "description": "Requested number of managed prompts. The app makes round(n/3) scenarios, clamped to 3-100, so values above 300 act as 300. UI start page offers 72, 90, 120, 180, 300 (72 preselected); the confirm page allows 6-300 in steps of 6. Server default when omitted: 24.", "schema": {"type": "integer", "default": 72, "minimum": 6, "maximum": 300}}]}}, "/history/count": {"get": {"operationId": "list_history_count", "summary": "History count", "description": "Number of saved runs in the history (for the header). Signed-in members only: {n}. 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)"}}}}, "/history/recent": {"get": {"operationId": "list_recent_history", "summary": "Your recent runs", "description": "Your 10 most recent runs as an HTML table fragment for the home page (time, brand, market, re-run/view/export/delete). Signed-in members only; each member sees only their own runs. 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)"}}}}}, "externalDocs": {"url": "https://daas-prompt.listeningmind.ai/agents.md", "description": "Agent guide"}}