# Keats > Shows a company how AI assistants (ChatGPT, Gemini, Google AI Overviews, AI Mode, Perplexity) answer the questions its buyers ask, turns each gap into a piece of work, and proves whether the work moved the numbers. Built to be run by your AI agent. ## Connect an agent Setup is at https://getkeats.com/docs/agents. - MCP server (Streamable HTTP): https://getkeats.com/mcp, header `Authorization: Bearer `. The server's instructions teach the method; its prompts are the workflows (weekly_cycle, weekly_review, work_action, tune_prompts). - Claude Code: `claude mcp add --transport http keats https://getkeats.com/mcp --header "Authorization: Bearer $KEATS_API_KEY"` - Keys: in the app, Settings → API keys (read or read-write, one workspace). - Then ask: "Run this week's Keats cycle for our brand and file a ticket for every card." ## Pages - [Home](https://getkeats.com/): what Keats does, a sample week, who it's for - [How it works](https://getkeats.com/how-it-works): the method (measure, diagnose, do the work, prove it) - [For agents](https://getkeats.com/agents): what your agent can do with Keats (a sales page; setup is in the docs, below) - [Pricing](https://getkeats.com/pricing): the plans, question packs, the trial and the FAQ - [Request early access](https://getkeats.com/request-access): sign-up is by approved address until general availability - [Privacy](https://getkeats.com/privacy) and [terms](https://getkeats.com/terms) ## Docs - [Connect an agent](https://getkeats.com/docs/agents): setup (the MCP server, the key, the first question to ask) - [API reference](https://getkeats.com/docs/api): auth, quickstart, errors, rate limits - [OpenAPI 3.1 spec](https://getkeats.com/api/v1/openapi.json) ## The weekly cycle (a brand, every card) 1. Read the portfolio: every offering's headline numbers by engine, the change since the previous read with its noise band, flags (a drop beyond noise; a rival named without you on buying answers) and open cards. Sort by attention. (get_brand_read) 2. For each flagged offering, read the week and the answers behind its biggest gaps. (get_weekly_read, explain_prompt, list_answers) 3. Check coverage: the plan recommends each offering's level (full, light or none) by its share of 12-month demand, with the questions it would add against the plan's limit (get_usage). It's a recommendation for the customer; only they act on it (track_offerings). Offerings and phrasings on the not-tracking list stay out. (get_coverage_plan, list_not_tracking) 4. Keep each offering's prompts sharp: retire generic ones (they name neither the offering nor the brand), add prompts for the ways buyers ask that are missing, each with tier, kind and why. (suggest_prompts, check_prompts, add_prompts, retire_prompts) 5. File every open card exactly once: list_brand_actions with ticketed=false, file a ticket in your tracker for each (get_brief is its body), then link_ticket with its URL. (list_brand_actions, link_ticket) 6. When a change is live, report its URL and date: that starts its evaluation at day 21 and day 35. (complete_action, record_external_work) 7. Close the week: get_summary returns what changed per offering (prompts, headline moves, new cards, cards done, evaluations read, new offerings found) and the same as markdown for a ticket comment. (get_summary) Diagnosis writes a card for every gap worth fixing, grouped by the fix, ranked by the visibility each could recover; fact_check cards name a wrong or inconsistent statement about the brand, where it appears and the source to correct against. ## Connections and history - Search Console: a person connects it in the app with Google (read-only; an agent can't grant Google access): get_search_console_status returns the connectUrl to send them, the connected account and its health. The other way is Keats's service account added as a Restricted user, then check_search_console with method service_account. disconnect_search_console revokes it. Once connected, suggest_prompts(offering) turns the offering's real searches into prompts (tracker noise listed apart), and the coverage plan uses 12 months of impressions on each offering's pages. - Mentions: get_mentions shows mentions across AI answers for the past four weeks (DataForSEO LLM Mentions, ChatGPT and Google), pulled when an offering is prepared; refresh_mentions pulls again. - Not tracking: add_not_tracking(offering or phrasing, why, revisitOn) keeps discovery, the catalog and suggestions from proposing it again. ## Reports and exports - Share a report: create_report_link(brandId, or offeringId; days 7, 30 or 90) returns a read-only URL anyone can open without signing in, for a client or a boss: the week in one sentence, the headline numbers with context, the trend, the brand against its rivals, the sources cited, work in progress and done, and results with verdicts. It never shows costs, settings, keys or members. list_report_links shows each link's state and views; revoke_report_link ends one now. get_report returns the same report as JSON; export_report_pdf as a PDF (application/pdf over REST, an embedded file over MCP). - export_questions_csv(offeringId): the latest read as CSV (RFC 4180, UTF-8 with a BOM, CRLF rows), one row per answer. Columns, in this fixed order (new ones only ever added at the end): offering, read_date, question, question_type, question_metric, question_result_percent, question_bar_percent, question_meets_bar, engine, sample, brand_named, brand_position, brand_cited, competitors_named, sources, our_pages_cited, answer. question_type is buying, preparing or facts; question_metric is named or cited, with question_result_percent and question_bar_percent beside it; booleans are yes or no; competitors_named, sources (domains) and our_pages_cited (URLs) are lists joined with " | "; a text cell that would start a spreadsheet formula is prefixed with an apostrophe. ## Plans and limits - Starter, $49/mo: 50 tracked questions, asked weekly on all five assistants; 1 brand; Unlimited teammates; Search Console connection; Diagnosis, action cards, briefs and evaluations; API and MCP server for your agent - Growth, $149/mo: 200 tracked questions, asked weekly on all five assistants; 3 brands; Unlimited teammates; Search Console connection; Diagnosis, action cards, briefs and evaluations; API and MCP server for your agent - Agency, $399/mo: 750 tracked questions, asked weekly on all five assistants; Unlimited brands; Unlimited teammates; Unlimited client workspaces; Search Console connection; Diagnosis, action cards, briefs and evaluations; API and MCP server for your agent - Question packs on any plan: +50 questions for $40/mo each. - Prices in US dollars, billed monthly, plus any tax. Keats sells through Stripe Managed Payments: Stripe is the merchant of record, adds any sales tax or VAT at checkout from the billing address, and sends the receipts. get_plan's prices.tax says the same. - A workspace starts its 14-day trial in Stripe Checkout, with a card, on the plan a person picks (Growth unless they choose another); nothing is charged until it ends, and it becomes the paid plan unless cancelled. Until the trial has started nothing is spent: add_brand, read_site_again, prepare_offerings, runs and approving questions fail with plan_required (402), whose `url` is the page a person opens to start it. Billing is monthly. - Limits apply where work is added (approving or adding prompts, preparing offerings, adding brands, inviting people), never to work already tracked. Over a limit an adding call fails with plan_limit (402), its message giving the numbers and its hint the fix. A payment that fails keeps adding open for 7 days; data is never deleted. - get_plan returns the workspace's plan, standing and the price list; get_usage returns questions and brands against their limits, the people in the workspace (never limited) and this month's answers. A person changes the plan in the app, Settings → Billing. ## Rules - Auth: send a workspace key as `Authorization: Bearer aeo_…`. Make keys in the app under Settings → API keys (owners and admins). A key works in its own workspace only; another workspace's ids answer 404, as if they didn't exist. Read-only keys get 403 on writes. - Errors are JSON: `{"error": {"code", "message", "hint"}}`. The hint says what to do next. Codes: invalid_input 400, unauthorized and key_revoked 401, forbidden 403, not_found 404, method_not_allowed 405, conflict 409 (the app's rules refuse it now, e.g. a card can't jump the board), plan_required 402 (the workspace's trial hasn't started: a person opens the error's `url` to start it with a card), plan_limit 402 (the plan has no room for what you're adding, or adding is paused; the message has the numbers and the hint the fix), idempotency_mismatch 422, rate_limited 429, internal 500. - Rate limits: 120 requests and 30 writes a minute per key (MCP counts each request, and each write tool). Over a limit you get 429 with Retry-After; every REST response carries X-RateLimit-Limit, -Remaining and -Reset. - Inputs are strict: a field an operation doesn't take is refused by name (invalid_input), never ignored. - Lists return `{"data": [...], "nextCursor"}`; pass `cursor=` for the next page and `limit` (1–200, default 50). - Writes take an optional `Idempotency-Key` header: a retry with the same key and body gets the first response again (for 24 hours); the same key with a different body is refused. - Long work returns a job, never a held connection: add_brand, read_site_again, prepare_offerings and run_now. Poll GET /api/v1/jobs/{jobId} (get_job) every 30–60 seconds; each job says what to call next. - Plans: tracked questions and brands count against the workspace's plan (get_plan, get_usage). Every write made with a key is recorded: the key, the operation and what it acted on. ## Operations (MCP tool = REST endpoint) - search: GET /api/v1/search (Search the workspace) - get_brand_read: GET /api/v1/brands/{brandId}/read (The brand's portfolio read) - get_weekly_read: GET /api/v1/offerings/{offeringId}/read (The weekly read) - list_actions: GET /api/v1/offerings/{offeringId}/actions (List action cards, ranked) - list_brand_actions: GET /api/v1/brands/{brandId}/actions (List a brand's action cards, every offering) - get_summary: GET /api/v1/brands/{brandId}/summary (The week's summary, for a ticket comment) - get_brief: GET /api/v1/actions/{actionId}/brief (Get a content brief for a card) - explain_prompt: GET /api/v1/prompts/{promptId}/explain (Explain a prompt) - list_brands: GET /api/v1/brands (List brands) - get_brand: GET /api/v1/brands/{brandId} (Get a brand) - get_catalog: GET /api/v1/brands/{brandId}/catalog (Read a brand's catalog) - get_coverage_plan: GET /api/v1/brands/{brandId}/coverage (The brand's coverage plan) - list_not_tracking: GET /api/v1/brands/{brandId}/not-tracking (List what the brand leaves out) - get_search_console_status: GET /api/v1/brands/{brandId}/search-console (Search Console: status and how to connect) - list_offerings: GET /api/v1/offerings (List offerings) - get_offering: GET /api/v1/offerings/{offeringId} (Get an offering) - list_prompts: GET /api/v1/offerings/{offeringId}/prompts (List prompts with results) - check_prompts: GET /api/v1/offerings/{offeringId}/prompts/check (Check an offering's prompts) - suggest_prompts: GET /api/v1/offerings/{offeringId}/prompts/suggest (Prompts from the offering's real searches) - list_competitors: GET /api/v1/brands/{brandId}/competitors (List competitors) - list_runs: GET /api/v1/offerings/{offeringId}/runs (List runs) - read_by_engine: GET /api/v1/offerings/{offeringId}/read/engines (The read by engine) - read_by_prompt: GET /api/v1/offerings/{offeringId}/read/prompts (The read by prompt) - list_answers: GET /api/v1/offerings/{offeringId}/answers (List answers) - list_citations: GET /api/v1/offerings/{offeringId}/citations (Citations by domain or page) - brands_named: GET /api/v1/offerings/{offeringId}/brands-named (Brands named) - get_action: GET /api/v1/actions/{actionId} (Get an action card) - list_evaluations: GET /api/v1/offerings/{offeringId}/evaluations (List evaluations) - get_trend: GET /api/v1/offerings/{offeringId}/trend (The offering's trend over the weeks) - get_mentions: GET /api/v1/offerings/{offeringId}/mentions (Mentions across AI answers, past four weeks) - get_job: GET /api/v1/jobs/{jobId} (Get a job) - list_jobs: GET /api/v1/jobs (List jobs) - get_plan: GET /api/v1/plan (The workspace's plan) - get_usage: GET /api/v1/usage (The workspace's usage against its plan) - list_notifications: GET /api/v1/notifications (List the workspace's notifications) - get_setup: GET /api/v1/setup (The first-run checklist) - get_email_preferences: GET /api/v1/email-preferences (Who gets the weekly email) - get_report: GET /api/v1/report (The shareable report, as data) - list_report_links: GET /api/v1/report-links (List shared report links) - export_report_pdf: GET /api/v1/report.pdf (The report as a PDF) - export_questions_csv: GET /api/v1/offerings/{offeringId}/questions.csv (Questions, answers, sources and rivals as CSV) - get_workspace: GET /api/v1/workspace (Get the workspace) - export_workspace: GET /api/v1/workspace/export (Export the workspace's data) - list_audit_log: GET /api/v1/audit-log (List the audit log) - add_brand: POST /api/v1/brands (Add a brand) - check_search_console: POST /api/v1/brands/{brandId}/search-console/check (Search Console: check the connection or choose the property) - disconnect_search_console: POST /api/v1/brands/{brandId}/search-console/disconnect (Search Console: disconnect) - track_offerings: POST /api/v1/brands/{brandId}/track (Set offerings' tracking levels) - add_not_tracking: POST /api/v1/brands/{brandId}/not-tracking (Leave an offering or a phrasing out) - remove_not_tracking: POST /api/v1/not-tracking/{entryId}/remove (Take an entry off the not-tracking list) - read_site_again: POST /api/v1/brands/{brandId}/read-site (Read the site again) - prepare_offerings: POST /api/v1/brands/{brandId}/prepare (Pick offerings to track) - decline_offering: POST /api/v1/offerings/{offeringId}/decline (Don't track an offering) - retry_offering: POST /api/v1/offerings/{offeringId}/retry (Try an offering's preparation again) - diagnose_again: POST /api/v1/offerings/{offeringId}/diagnose (Diagnose the latest read again) - start_tracking: POST /api/v1/brands/{brandId}/start-tracking (Finish setup: start tracking) - update_offering: PATCH /api/v1/offerings/{offeringId} (Change an offering's settings) - add_prompt: POST /api/v1/offerings/{offeringId}/prompts (Add a prompt) - add_prompts: POST /api/v1/offerings/{offeringId}/prompts/bulk (Add prompts in bulk) - edit_prompt: PATCH /api/v1/prompts/{promptId} (Edit a prompt) - approve_all_prompts: POST /api/v1/offerings/{offeringId}/prompts/approve-all (Approve all proposed prompts of an offering) - approve_prompts: POST /api/v1/prompts/approve (Approve prompts) - reject_prompts: POST /api/v1/prompts/reject (Reject proposed prompts) - retire_prompt: POST /api/v1/prompts/{promptId}/retire (Retire a prompt) - retire_prompts: POST /api/v1/prompts/retire (Retire prompts in bulk) - add_competitor: POST /api/v1/brands/{brandId}/competitors (Add a competitor) - update_competitor: PATCH /api/v1/competitors/{competitorId} (Change a competitor) - review_competitors: POST /api/v1/competitors/review (Review competitors in one call) - run_now: POST /api/v1/offerings/{offeringId}/runs (Run a read now) - refresh_mentions: POST /api/v1/offerings/{offeringId}/mentions/refresh (Pull mentions across AI answers again) - delete_imported_history: POST /api/v1/offerings/{offeringId}/history/delete-imported (Delete an offering's legacy imported history) - link_ticket: POST /api/v1/actions/{actionId}/ticket (Link a card to its ticket) - accept_action: POST /api/v1/actions/{actionId}/accept (Accept a card) - dismiss_action: POST /api/v1/actions/{actionId}/dismiss (Dismiss a card) - move_action: POST /api/v1/actions/{actionId}/move (Move a card) - complete_action: POST /api/v1/actions/{actionId}/complete (Report a card's work done) - record_external_work: POST /api/v1/offerings/{offeringId}/work (Record work done outside a card) - mark_notifications_read: POST /api/v1/notifications/read (Mark notifications read) - dismiss_setup: POST /api/v1/setup/dismiss (Hide or show the first-run checklist) - dismiss_sample: POST /api/v1/sample/dismiss (Hide or show the sample brand) - update_email_preferences: PATCH /api/v1/email-preferences (Turn your weekly email on or off) - send_weekly_email_preview: POST /api/v1/email-preferences/preview (Send me a preview of the weekly email) - create_report_link: POST /api/v1/report-links (Share a report by link) - revoke_report_link: POST /api/v1/report-links/{linkId}/revoke (Turn off a report link) - rename_workspace: PATCH /api/v1/workspace (Rename the workspace) - delete_workspace: POST /api/v1/workspace/delete (Delete the workspace) ## Guides (3) - [AEO vs SEO vs GEO: what's actually different](https://getkeats.com/guides/aeo-vs-seo.md): AEO and GEO name the same job. What changes from SEO is the unit (an answer, not a ranking) and the measure (named and cited, not position). - [AEO with your AI agent: the weekly loop over MCP](https://getkeats.com/guides/aeo-with-your-ai-agent.md): Point Claude, ChatGPT or Cursor at Keats's MCP server and your agent runs the AEO loop: reads the gaps, drafts the fix, reports it live. - [How to rank in ChatGPT: get your brand named in its answers](https://getkeats.com/guides/get-named-in-chatgpt.md): ChatGPT names the brands on the pages it reads. How an answer is built, the four fixes in the order that works, and how to tell if one worked. ## Glossary (16) - [What is an action card in Keats?](https://getkeats.com/glossary/action-card.md): An action card is one piece of AEO work: a gap, why it happens, the change to make, the questions it targets, and later, its verdict. - [What is AEO? Answer engine optimization in plain words](https://getkeats.com/glossary/aeo.md): AEO, answer engine optimization, is the work of getting your brand named and your pages cited in the answers AI assistants write. - [What are Google AI Overviews, and how do pages get cited?](https://getkeats.com/glossary/ai-overviews.md): Google AI Overviews are the written summaries above search results. How they choose their sources, and what that means for your pages. - [What is an AI visibility score, and how is it weighted?](https://getkeats.com/glossary/ai-visibility-score.md): An AI visibility score rolls up how often AI answers name and cite you into one number. How Keats weights it, and what it hides. - [What is AI visibility? How often AI answers name your brand](https://getkeats.com/glossary/ai-visibility.md): AI visibility is how often AI assistants name your brand and cite your pages when buyers ask about what you sell, measured over many answers. - [What is an answer engine? ChatGPT, Gemini, Perplexity and more](https://getkeats.com/glossary/answer-engine.md): An answer engine replies to a question with a written answer instead of a list of links: ChatGPT, Gemini, Perplexity and Google's AI features. - [What is a citation in an AI answer?](https://getkeats.com/glossary/citation.md): A citation is a link an AI answer gives as its source. Being cited differs from being named, and it matters most on fact questions. - [Control questions: how to prove an AEO change worked](https://getkeats.com/glossary/control-questions.md): Control questions are tracked questions your change didn't target. If they rise as much as the targets, the market moved, not your page. - [What is query fan-out? The searches AI assistants run](https://getkeats.com/glossary/fan-out-searches.md): Query fan-out is the set of searches an AI assistant runs before it answers. They decide which pages it reads, and so which brands it names. - [What is generative engine optimization (GEO)?](https://getkeats.com/glossary/geo.md): Generative engine optimization, GEO, is another name for AEO: getting named and cited in AI-written answers. Where the term came from. - [What is llms.txt, and should your site have one?](https://getkeats.com/glossary/llms-txt.md): llms.txt is a proposed file that tells AI agents what's on your site and where to read it. What it does, what it doesn't, and whether to add one. - [What is MCP? The Model Context Protocol, for marketers](https://getkeats.com/glossary/mcp.md): MCP, the Model Context Protocol, is how AI agents like Claude and ChatGPT connect to outside tools. What it means for AEO work. - [What does named first mean in AI answers?](https://getkeats.com/glossary/named-first.md): Named first is the share of AI answers that mention your brand before any rival. On buying questions, it's the number closest to a sale. - [What is a noise band in AI visibility tracking?](https://getkeats.com/glossary/noise-band.md): AI answers vary from one ask to the next. A noise band is the range a number moves by chance, so you can tell a real change from luck. - [What is prompt tracking in AEO, and which prompts to track?](https://getkeats.com/glossary/prompt-tracking.md): Prompt tracking means asking AI assistants a fixed set of buyers' questions every week and counting who gets named. How to choose them. - [Question tiers in AEO: buying, preparing and facts](https://getkeats.com/glossary/question-tiers.md): Not every question is worth the same. Tier 1 is buying, tier 2 is preparing, tier 3 is facts; each has its own aim and its own weight.