{"openapi":"3.1.0","info":{"title":"Moatlight API","version":"1.1.0","summary":"Measure how ChatGPT and Google AI Overview name a business, and get a ranked plan of changes.","description":"Public endpoints need no login. Account and report endpoints need an OAuth 2.0 access token (authorization code with PKCE); apps can use a client_id metadata URL (CIMD) or register themselves (RFC 7591). The free plan allows one website and one report every 30 days. The Early Access pass adds the agent readiness endpoints. A sandbox with made-up data needs no login.","contact":{"name":"Moatlight","email":"ceo@moatlight.com","url":"https://www.moatlight.com/docs"},"x-api-lifecycle":{"version_scheme":"The major version is in the path (/api/v1). Inside a major version changes only add things: new endpoints, optional fields, new enum values. Clients must ignore fields they do not know.","deprecation_policy":"A deprecated endpoint or field keeps working for at least 180 days after announcement. During that time every answer carries a Deprecation header (RFC 9745) and a Sunset header (RFC 8594) with the removal date, plus a Link header (rel=\"deprecation\") to the notice. Breaking changes ship only in a new major version served beside the old one. Policy: https://www.moatlight.com/docs#versioning","current_status":"v1 is current. No endpoint is deprecated and no sunset date is set.","changelog":"https://www.moatlight.com/docs#versioning"},"x-rate-limits":"Public endpoints: 120 requests per minute per IP. Signed-in endpoints: 120 per minute per user, and report starts and scans have hourly caps. Every answer carries RateLimit and RateLimit-Policy (IETF draft-ietf-httpapi-ratelimit-headers) and the older RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset; a 429 adds Retry-After.","x-idempotency":"POST operations that start work accept an Idempotency-Key header (1 to 255 printable characters, for example a UUID). A retry with the same key and body returns the first answer with Idempotent-Replayed: true; the same key with a different body answers 422. Keys live 24 hours.","x-pagination":"List endpoints take ?limit= (1 to 50, default 20) and ?cursor=. The answer has next_cursor (null on the last page) and has_more."},"servers":[{"url":"https://www.moatlight.com","description":"Production"},{"url":"https://www.moatlight.com","description":"Sandbox: same origin, but call the /api/v1/sandbox/* paths (base https://www.moatlight.com/api/v1/sandbox). Made-up data, no login, no cost, nothing real is touched."}],"externalDocs":{"description":"Human documentation","url":"https://www.moatlight.com/docs"},"tags":[{"name":"Public"},{"name":"Account"},{"name":"Reports"},{"name":"Agent readiness"},{"name":"Sandbox"}],"paths":{"/api/v1/product":{"get":{"operationId":"getProduct","summary":"What Moatlight does and when to use it","description":"Facts about the product: what it does, who it is for, what it does not do, and how an agent can use it. No login.","tags":["Public"],"security":[],"parameters":[{"name":"fields","in":"query","required":false,"description":"Comma-separated top-level fields to return, for example fields=id,stage. Omit to get everything. Spend fewer tokens by asking for less.","schema":{"type":"string","maxLength":200,"examples":["id,stage"]}}],"responses":{"200":{"description":"Product facts.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}},"/api/v1/pricing":{"get":{"operationId":"getPricing","summary":"Plans and prices","description":"The free plan and the one-time Early Access pass: price, what each includes, refund window. Payment needs a person in a browser. No login.","tags":["Public"],"security":[],"parameters":[{"name":"fields","in":"query","required":false,"description":"Comma-separated top-level fields to return, for example fields=id,stage. Omit to get everything. Spend fewer tokens by asking for less.","schema":{"type":"string","maxLength":200,"examples":["id,stage"]}}],"responses":{"200":{"description":"Plans.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pricing"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}},"/api/v1/faq":{"get":{"operationId":"listFaq","summary":"Frequently asked questions","description":"Every FAQ question and answer from the home page, paged. No login.","tags":["Public"],"security":[],"parameters":[{"name":"limit","in":"query","required":false,"description":"Items per page, 1 to 50. Default 20.","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor: send next_cursor from the previous page unchanged. Omit for the first page.","schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"A page of question and answer pairs, with next_cursor and has_more.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"faq":{"type":"array","items":{"type":"object","properties":{"question":{"type":"string"},"answer":{"type":"string"}}}}},"required":["faq"]}]}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}},"/api/v1/sample-report":{"get":{"operationId":"getSampleReport","summary":"A finished sample report on made-up data","description":"Shows the shape of a real report (visibility numbers, rivals, ranked plan) for a fictional coffee roaster. Made-up data, no login.","tags":["Public"],"security":[],"parameters":[{"name":"fields","in":"query","required":false,"description":"Comma-separated top-level fields to return, for example fields=id,stage. Omit to get everything. Spend fewer tokens by asking for less.","schema":{"type":"string","maxLength":200,"examples":["id,stage"]}}],"responses":{"200":{"description":"A sample report.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Report"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}},"/api/v1/me":{"get":{"operationId":"getAccount","summary":"The signed-in user, plan and limits","description":"Returns the user's plan (free or early_access), when the pass ends, what the plan allows, and how to upgrade.","tags":["Account"],"security":[{"oauth2":["account:read"]}],"parameters":[{"name":"fields","in":"query","required":false,"description":"Comma-separated top-level fields to return, for example fields=id,stage. Omit to get everything. Spend fewer tokens by asking for less.","schema":{"type":"string","maxLength":200,"examples":["id,stage"]}}],"responses":{"200":{"description":"Account, plan and limits.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"description":"No valid bearer token. The WWW-Authenticate header points to the protected resource metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"description":"Bearer resource_metadata=... (RFC 9728)","schema":{"type":"string"}}}},"403":{"description":"The token lacks the required scope, or the plan does not allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}},"/api/v1/reports":{"get":{"operationId":"listReports","summary":"List the user's reports","description":"The user's reports, newest first, paged with a cursor. Each has its stage (analyzing, needs_confirmation, running, finished, failed).","tags":["Reports"],"security":[{"oauth2":["reports:read"]}],"parameters":[{"name":"limit","in":"query","required":false,"description":"Items per page, 1 to 50. Default 20.","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor: send next_cursor from the previous page unchanged. Omit for the first page.","schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"A page of reports, with next_cursor and has_more.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"reports":{"type":"array","items":{"$ref":"#/components/schemas/ReportItem"}}},"required":["reports"]}]}}}},"401":{"description":"No valid bearer token. The WWW-Authenticate header points to the protected resource metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"description":"Bearer resource_metadata=... (RFC 9728)","schema":{"type":"string"}}}},"403":{"description":"The token lacks the required scope, or the plan does not allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}},"post":{"operationId":"createReport","summary":"Start a report for a website","description":"Creates a report draft for a website and starts reading it. Free plan: one website, one report every 30 days. Returns 202 Accepted with the report, a job object and a Location header: poll that URL (GET /api/v1/reports/{reportId}) every few seconds until stage is needs_confirmation, then call the start endpoint. Send an Idempotency-Key header so a retry cannot start a second report.","tags":["Reports"],"security":[{"oauth2":["reports:write"]}],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["website"],"properties":{"website":{"type":"string","description":"The website to measure, like yourcompany.com. Public sites only.","examples":["yourcompany.com"]},"country":{"type":"string","description":"Optional two-letter country. Send with language, or omit both to detect from the site."},"language":{"type":"string","description":"Optional language for that country."}}}}}},"responses":{"200":{"description":"Nothing left to wait for (for example a report that was already finished): the report as it is now.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Report"}}}},"202":{"description":"The new (or resumed) report. Work goes on after the answer: poll the Location URL. The body has job_id, status_url and poll_after_seconds.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Location":{"description":"URL to poll (GET) for the result.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before the first poll.","schema":{"type":"integer"}},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Report"}}}},"400":{"description":"The request is malformed. See error.hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token. The WWW-Authenticate header points to the protected resource metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"description":"Bearer resource_metadata=... (RFC 9728)","schema":{"type":"string"}}}},"403":{"description":"The token lacks the required scope, or the plan does not allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The action does not fit the report's current stage or limits, or the first request with this Idempotency-Key is still running (code request_in_progress, see Retry-After).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The input was understood but cannot be used (for example an unreachable website), or the Idempotency-Key was already used for a different request (code idempotency_key_reused).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}},"503":{"description":"This feature is unavailable right now.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/reports/batch":{"post":{"operationId":"batchGetReports","summary":"Read up to 25 reports in one request","description":"Batch read: send a list of report ids and get each report (or its error) in one answer, instead of one call per report. Each result has its own status, so one unknown id does not fail the rest. Read-only.","tags":["Reports"],"security":[{"oauth2":["reports:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["report_ids"],"properties":{"report_ids":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":25,"description":"Report ids to read, 1 to 25."}}}}}},"x-readOnly":true,"responses":{"200":{"description":"One result per id, with succeeded and failed counts.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResult"}}}},"400":{"description":"The request is malformed. See error.hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token. The WWW-Authenticate header points to the protected resource metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"description":"Bearer resource_metadata=... (RFC 9728)","schema":{"type":"string"}}}},"403":{"description":"The token lacks the required scope, or the plan does not allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}},"/api/v1/reports/{reportId}":{"get":{"operationId":"getReport","summary":"Read one report: stage, setup to confirm, or results","description":"While stage is needs_confirmation it returns the business profile and the proposed buyer questions. While running it returns progress. When finished it returns visibility numbers, the brands AI named, and a count of lost questions.","tags":["Reports"],"security":[{"oauth2":["reports:read"]}],"parameters":[{"name":"reportId","in":"path","required":true,"description":"Report id from POST /api/v1/reports or GET /api/v1/reports.","schema":{"type":"string"}},{"name":"fields","in":"query","required":false,"description":"Comma-separated top-level fields to return, for example fields=id,stage. Omit to get everything. Spend fewer tokens by asking for less.","schema":{"type":"string","maxLength":200,"examples":["id,stage"]}}],"responses":{"200":{"description":"The report in its current stage.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Report"}}}},"401":{"description":"No valid bearer token. The WWW-Authenticate header points to the protected resource metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"description":"Bearer resource_metadata=... (RFC 9728)","schema":{"type":"string"}}}},"403":{"description":"The token lacks the required scope, or the plan does not allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such item for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}},"/api/v1/reports/{reportId}/start":{"post":{"operationId":"startReport","summary":"Confirm the setup and run the report","description":"Accepts the proposed business profile and buyer questions (optionally a chosen subset of 3 to 6 question ids) and starts asking the AI engines. Takes about two minutes: answers 202 Accepted with a Location header to poll until stage is finished. Safe to repeat; send an Idempotency-Key header to make a retry return the first answer.","tags":["Reports"],"security":[{"oauth2":["reports:write"]}],"parameters":[{"name":"reportId","in":"path","required":true,"description":"Report id from POST /api/v1/reports or GET /api/v1/reports.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"question_ids":{"type":"array","items":{"type":"string"},"description":"Ids of the 3 to 6 questions to ask. Omit to keep the proposed selection."}}}}}},"responses":{"200":{"description":"Nothing left to wait for (for example a report that was already finished): the report as it is now.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Report"}}}},"202":{"description":"The report, now running. Work goes on after the answer: poll the Location URL. The body has job_id, status_url and poll_after_seconds.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Location":{"description":"URL to poll (GET) for the result.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before the first poll.","schema":{"type":"integer"}},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Report"}}}},"400":{"description":"The request is malformed. See error.hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token. The WWW-Authenticate header points to the protected resource metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"description":"Bearer resource_metadata=... (RFC 9728)","schema":{"type":"string"}}}},"403":{"description":"The token lacks the required scope, or the plan does not allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such item for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The action does not fit the report's current stage or limits, or the first request with this Idempotency-Key is still running (code request_in_progress, see Retry-After).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The input was understood but cannot be used (for example an unreachable website), or the Idempotency-Key was already used for a different request (code idempotency_key_reused).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}},"/api/v1/reports/{reportId}/actions":{"get":{"operationId":"getReportActions","summary":"The ranked plan of changes and the questions you lost","description":"For a finished report: up to three ranked moves (reason, exact edit, page, effort) and, for each buyer question AI answered with a rival, who won and why.","tags":["Reports"],"security":[{"oauth2":["reports:read"]}],"parameters":[{"name":"reportId","in":"path","required":true,"description":"Report id from POST /api/v1/reports or GET /api/v1/reports.","schema":{"type":"string"}},{"name":"fields","in":"query","required":false,"description":"Comma-separated top-level fields to return, for example fields=id,stage. Omit to get everything. Spend fewer tokens by asking for less.","schema":{"type":"string","maxLength":200,"examples":["id,stage"]}}],"responses":{"200":{"description":"Moves and lost questions.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Actions"}}}},"401":{"description":"No valid bearer token. The WWW-Authenticate header points to the protected resource metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"description":"Bearer resource_metadata=... (RFC 9728)","schema":{"type":"string"}}}},"403":{"description":"The token lacks the required scope, or the plan does not allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such item for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The action does not fit the report's current stage or limits, or the first request with this Idempotency-Key is still running (code request_in_progress, see Retry-After).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}},"/api/v1/reports/{reportId}/agent-readiness":{"get":{"operationId":"getAgentReadiness","summary":"Stored agent readiness scan (Early Access pass)","description":"Score, grade, layer breakdown and ranked fixes from the newest scan of the report's website. Needs the Early Access pass; otherwise 402 with a link a person can open to buy it.","tags":["Agent readiness"],"security":[{"oauth2":["agent-readiness:read"]}],"parameters":[{"name":"reportId","in":"path","required":true,"description":"Report id from POST /api/v1/reports or GET /api/v1/reports.","schema":{"type":"string"}},{"name":"fields","in":"query","required":false,"description":"Comma-separated top-level fields to return, for example fields=id,stage. Omit to get everything. Spend fewer tokens by asking for less.","schema":{"type":"string","maxLength":200,"examples":["id,stage"]}}],"responses":{"200":{"description":"The newest scan.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentScan"}}}},"401":{"description":"No valid bearer token. The WWW-Authenticate header points to the protected resource metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"description":"Bearer resource_metadata=... (RFC 9728)","schema":{"type":"string"}}}},"402":{"description":"Needs the Early Access pass. error.upgrade_url is a page where a person can buy it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The token lacks the required scope, or the plan does not allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such item for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}},"/api/v1/reports/{reportId}/agent-readiness/scan":{"post":{"operationId":"scanAgentReadiness","summary":"Run an agent readiness scan (Early Access pass)","description":"Runs, or reuses a result under 24 hours old, for the report's website. Set force to true to scan again after fixing something. Rate limited.","tags":["Agent readiness"],"security":[{"oauth2":["agent-readiness:scan"]}],"parameters":[{"name":"reportId","in":"path","required":true,"description":"Report id from POST /api/v1/reports or GET /api/v1/reports.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"force":{"type":"boolean","description":"Scan again even if a recent result exists."}}}}}},"responses":{"200":{"description":"The scan.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentScan"}}}},"401":{"description":"No valid bearer token. The WWW-Authenticate header points to the protected resource metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"description":"Bearer resource_metadata=... (RFC 9728)","schema":{"type":"string"}}}},"402":{"description":"Needs the Early Access pass. error.upgrade_url is a page where a person can buy it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The token lacks the required scope, or the plan does not allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such item for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The action does not fit the report's current stage or limits, or the first request with this Idempotency-Key is still running (code request_in_progress, see Retry-After).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The input was understood but cannot be used (for example an unreachable website), or the Idempotency-Key was already used for a different request (code idempotency_key_reused).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}},"502":{"description":"An upstream scanner failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/sandbox/me":{"get":{"operationId":"sandboxGetAccount","summary":"Sandbox: a fake account on the Early Access pass","description":"No login, no cost, made-up data. Same shape as GET /api/v1/me. Use the sandbox to test an integration before you ask a user to log in.","tags":["Sandbox"],"security":[],"parameters":[{"name":"fields","in":"query","required":false,"description":"Comma-separated top-level fields to return, for example fields=id,stage. Omit to get everything. Spend fewer tokens by asking for less.","schema":{"type":"string","maxLength":200,"examples":["id,stage"]}}],"responses":{"200":{"description":"A fake account.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}},"/api/v1/sandbox/reports":{"get":{"operationId":"sandboxListReports","summary":"Sandbox: list reports","description":"One finished sample report. Same shape as GET /api/v1/reports. No login.","tags":["Sandbox"],"security":[],"parameters":[{"name":"limit","in":"query","required":false,"description":"Items per page, 1 to 50. Default 20.","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor: send next_cursor from the previous page unchanged. Omit for the first page.","schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"A list with one report.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"reports":{"type":"array","items":{"$ref":"#/components/schemas/ReportItem"}}},"required":["reports"]}]}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}},"post":{"operationId":"sandboxCreateReport","summary":"Sandbox: pretend to start a report","description":"Accepts the same body as POST /api/v1/reports, validates it, and returns a fake report in stage analyzing. Nothing is read or charged. No login.","tags":["Sandbox"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["website"],"properties":{"website":{"type":"string","description":"Any website name."}}}}}},"responses":{"200":{"description":"Nothing left to wait for (for example a report that was already finished): the report as it is now.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Report"}}}},"202":{"description":"A fake report. Work goes on after the answer: poll the Location URL. The body has job_id, status_url and poll_after_seconds.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Location":{"description":"URL to poll (GET) for the result.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before the first poll.","schema":{"type":"integer"}},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Report"}}}},"400":{"description":"The request is malformed. See error.hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}},"/api/v1/sandbox/reports/{reportId}":{"get":{"operationId":"sandboxGetReport","summary":"Sandbox: read a finished sample report","description":"Any report id returns the same finished sample report on made-up data. No login.","tags":["Sandbox"],"security":[],"parameters":[{"name":"reportId","in":"path","required":true,"description":"Report id from POST /api/v1/reports or GET /api/v1/reports.","schema":{"type":"string"}},{"name":"fields","in":"query","required":false,"description":"Comma-separated top-level fields to return, for example fields=id,stage. Omit to get everything. Spend fewer tokens by asking for less.","schema":{"type":"string","maxLength":200,"examples":["id,stage"]}}],"responses":{"200":{"description":"A finished sample report.","headers":{"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Report"}}}},"429":{"description":"Too many requests. Retry-After says how many seconds to wait; the RateLimit headers show the quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}},"API-Version":{"$ref":"#/components/headers/API-Version"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}}}}}}},"components":{"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string","description":"What went wrong."},"hint":{"type":"string","description":"What to do next."},"docs":{"type":"string","description":"Where the error is documented."}},"required":["code","message"]}},"required":["error"]},"Account":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","description":"User id."},"email":{"type":"string","description":"Email."},"name":{"type":"string","description":"Name."}}},"plan":{"type":"string","description":"Current plan.","enum":["free","early_access"]},"plan_expires_at":{"type":["string","null"],"format":"date-time","description":"When the Early Access pass ends."},"limits":{"type":"object","properties":{"websites":{"type":"integer","description":"Websites allowed."},"report_interval_days":{"type":"integer","description":"Days between reports of one site."}}},"features":{"type":"object","properties":{"reports":{"type":"boolean"},"agent_readiness":{"type":"boolean"}}},"upgrade":{"type":["object","null"],"description":"How a person can upgrade; null when not applicable."}},"required":["user","plan","limits","features"]},"ReportItem":{"type":"object","properties":{"id":{"type":"string","description":"Report id."},"website":{"type":"string","description":"Website domain."},"stage":{"type":"string","description":"Where the report is.","enum":["analyzing","analysis_failed","needs_confirmation","running","finished","failed"]},"created_at":{"type":"string","description":"Creation time.","format":"date-time"},"url":{"type":"string","description":"API URL of the report."}},"required":["id","website","stage"]},"Report":{"type":"object","properties":{"id":{"type":"string","description":"Report id."},"website":{"type":"string","description":"Website domain."},"stage":{"type":"string","description":"Where the report is.","enum":["analyzing","analysis_failed","needs_confirmation","running","finished","failed"]},"created_at":{"type":"string","description":"Creation time.","format":"date-time"},"next_step":{"type":"string","description":"What to do next, in words."},"job_id":{"type":"string","description":"On a 202 answer: the id to poll (same as id)."},"status_url":{"type":"string","description":"On a 202 answer: GET this URL until the work is done (same as the Location header)."},"poll_after_seconds":{"type":"integer","description":"On a 202 answer: seconds to wait between polls."},"job":{"$ref":"#/components/schemas/Job"},"progress":{"type":"object","properties":{"answers_done":{"type":"integer","description":"Answers back so far."},"answers_total":{"type":"integer","description":"Answers planned."}}},"error":{"type":"string","description":"Reason when a step failed."},"human_view":{"type":"string","description":"Where a person can open this report."},"profile":{"type":"object","properties":{"name":{"type":"string","description":"Business name."},"description":{"type":"string","description":"Description."},"category":{"type":"string","description":"Category."},"country":{"type":"string","description":"Country."},"language":{"type":"string","description":"Language."},"audiences":{"type":"array","items":{"type":"string"}},"competitors":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"site":{"type":"string"}}}}}},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"question":{"type":"string"},"audience":{"type":"string"},"included":{"type":"boolean"}}}},"summary":{"type":"object","properties":{"business":{"type":"string"},"answers":{"type":"integer","description":"Answers counted."},"named":{"type":"integer","description":"Answers that named the business."},"cited_on_your_site":{"type":"integer","description":"Answers that cited the business's own site."},"share_of_voice":{"type":"object","properties":{"k":{"type":"integer"},"n":{"type":"integer"},"brands":{"type":"integer"}}},"rank":{"type":["object","null"],"properties":{"place":{"type":"integer"},"of":{"type":"integer"}}},"per_engine":{"type":"array","items":{"type":"object","properties":{"engine":{"type":"string"},"answers":{"type":"integer"},"named":{"type":"integer"}}}},"top_brands":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"appeared":{"type":"integer"},"own":{"type":"boolean"}}}},"lost_questions":{"type":"integer","description":"Buyer questions AI answered with a rival."}}}},"required":["id","website","stage"]},"Actions":{"type":"object","properties":{"report_id":{"type":"string"},"moves":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"title":{"type":"string"},"why":{"type":"string"},"todo":{"type":"string"},"draft":{"type":["string","null"]},"questions":{"type":"array","items":{"type":"string"}},"effort":{"type":"string"},"where":{"type":"string"},"recheck":{"type":"string"}}}},"lost_questions":{"type":"array","items":{"type":"object","properties":{"question":{"type":"string"},"answers":{"type":"integer"},"named":{"type":"integer"},"winner":{"type":["object","null"]},"reasons":{"type":"array","items":{"type":"string"}}}}}},"required":["report_id","moves"]},"AgentScan":{"type":"object","properties":{"domain":{"type":"string"},"scanned_at":{"type":"string","format":"date-time"},"status":{"type":"string","description":"Scan completeness.","enum":["complete","partial","stuck"]},"score":{"type":"integer","description":"Score."},"max_score":{"type":"integer","description":"Best possible score."},"grade":{"type":"string"},"essentials_score":{"type":["integer","null"]},"layers":{"type":"array","items":{"type":"object"}},"top_fixes":{"type":"array","items":{"type":"object"}}},"required":["domain","score","grade"]},"Job":{"type":"object","properties":{"id":{"type":"string","description":"Job id. For a report it is the report id."},"status":{"type":"string","description":"Where the work is: the report stage.","enum":["analyzing","analysis_failed","needs_confirmation","running","finished","failed"]},"status_url":{"type":"string","description":"GET this URL to poll."},"poll_after_seconds":{"type":"integer","description":"Wait this long between polls."},"done_when":{"type":"string","description":"What the status must be for the work to be done."}},"required":["id","status","status_url"]},"Page":{"type":"object","properties":{"next_cursor":{"type":["string","null"],"description":"Send this as ?cursor= to get the next page. null on the last page."},"has_more":{"type":"boolean","description":"True when another page exists."}},"required":["next_cursor","has_more"]},"Product":{"type":"object","properties":{"name":{"type":"string","description":"Product name."},"description":{"type":"string","description":"One-line description."},"what_it_does":{"type":"string","description":"What the product does."},"engines":{"type":"array","items":{"type":"string"}},"best_for":{"type":"array","items":{"type":"string"}},"not_for":{"type":"array","items":{"type":"string"}},"how_to_use":{"type":"object","properties":{"no_login":{"type":"string"},"with_login":{"type":"string"},"sandbox":{"type":"string"}}},"links":{"type":"object","properties":{"website":{"type":"string"},"docs":{"type":"string"},"openapi":{"type":"string"},"mcp":{"type":"string"},"llms_txt":{"type":"string"},"sample_report":{"type":"string"}}},"contact":{"type":"string","description":"Contact email."},"updated":{"type":"string","description":"Date the facts were last reviewed."}},"required":["name","description","what_it_does"]},"Pricing":{"type":"object","properties":{"currency":{"type":"string","description":"Currency code."},"plans":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Plan id.","enum":["free","early_access"]},"name":{"type":"string"},"price_usd":{"type":"number"},"card_required":{"type":"boolean"},"billing":{"type":"string"},"access_days":{"type":"integer"},"refund_days":{"type":"integer"},"includes":{"type":"array","items":{"type":"string"}},"seller_of_record":{"type":"string"},"buy_at":{"type":"string"},"note":{"type":"string"}},"required":["id","name","price_usd"]}}},"required":["currency","plans"]},"BatchResult":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"report_id":{"type":"string","description":"The id that was asked for."},"status":{"type":"integer","description":"HTTP-style status for this id: 200, 404."},"report":{"$ref":"#/components/schemas/Report"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"hint":{"type":"string"}},"required":["code","message"]}},"required":["report_id","status"]}},"succeeded":{"type":"integer","description":"Ids that returned a report."},"failed":{"type":"integer","description":"Ids that returned an error."}},"required":["results","succeeded","failed"]},"Generic":{"type":"object","additionalProperties":true}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retry safe: the same key and body return the first answer instead of doing the work twice. 1 to 255 printable characters, for example a UUID. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":255},"example":"7d1f6c52-0b6e-4c1e-9d0a-3f4f9a2b8c11"}},"headers":{"API-Version":{"description":"The API version that answered, for example 1.0.0.","schema":{"type":"string"}},"RateLimit":{"description":"IETF draft field: remaining quota and seconds to reset, for example \"default\";r=119;t=60.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"IETF draft field: the quota and window, for example \"default\";q=120;w=60.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Requests allowed in the window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in the window.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Idempotent-Replayed":{"description":"true when this answer is the saved result of an earlier request with the same Idempotency-Key.","schema":{"type":"string"}},"Deprecation":{"description":"Present only on a deprecated endpoint: when it was or will be deprecated (RFC 9745).","schema":{"type":"string"}},"Sunset":{"description":"Present only on a deprecated endpoint: the date it stops working (RFC 8594).","schema":{"type":"string"}}},"securitySchemes":{"oauth2":{"type":"oauth2","description":"Authorization code with PKCE. Authorization server: https://www.moatlight.com. Walkthrough: https://www.moatlight.com/auth.md","flows":{"authorizationCode":{"authorizationUrl":"https://www.moatlight.com/api/auth/oauth2/authorize","tokenUrl":"https://www.moatlight.com/api/auth/oauth2/token","refreshUrl":"https://www.moatlight.com/api/auth/oauth2/token","scopes":{"account:read":"Read your plan, limits and whether you hold the Early Access pass.","reports:read":"Read your reports: status, visibility numbers, competitors and the ranked plan.","reports:write":"Start a report for a website and confirm its setup. Uses your free report allowance.","agent-readiness:read":"Read the stored agent readiness scan of a report (Early Access pass).","agent-readiness:scan":"Run an agent readiness scan for a report (Early Access pass)."}}}},"openIdConnect":{"type":"openIdConnect","openIdConnectUrl":"https://www.moatlight.com/.well-known/openid-configuration"}}},"x-oidc-scopes":["openid","profile","email","offline_access"]}