{"openapi":"3.1.0","info":{"title":"index365 API","version":"1.0.0","description":"Run evidence and fix-path inputs for you and your agent workflow. Every workspace gets scoped API keys on every plan, including Free: read endpoints (projects, runs, findings, reports) work on any plan, while starting paid scans (runs:write) spends org credits and needs an active paid plan. Authenticate with a scoped API key from your dashboard: 'Authorization: Bearer i365_...'. Keys can be re-revealed from the dashboard.","contact":{"url":"https://index365.co/contact"}},"servers":[{"url":"https://index365.co"}],"security":[{"apiKey":[]}],"tags":[{"name":"authentication","description":"Browser-OAuth credential exchange for the CLI."},{"name":"introspection","description":"Key + tenancy diagnostics."},{"name":"projects","description":"Domain-anchored workspaces in your org."},{"name":"runs","description":"Audit runs: start, poll, inspect."},{"name":"findings","description":"Agent result contract v2 findings."},{"name":"reports","description":"Compact agent report context for a run or a project's latest scan."},{"name":"webhooks","description":"Event subscriptions (HMAC-signed deliveries)."}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Scoped API key created from the dashboard API Keys page (every plan, including Free). Secrets start with i365_ and can be re-revealed from the dashboard. Scopes: projects:read, projects:write, projects:delete, runs:read, runs:write, findings:read, reports:read"}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}},"AgentFinding":{"type":"object","description":"Agent result contract v2 finding. findingId is deterministic and stable for a given run.","required":["findingId","runId","category","status","severity","confidence","title","detail","evidence","affectedUrls","remediation","agentActions","humanUrl","createdAt","updatedAt"],"properties":{"findingId":{"type":"string","example":"f_1a2b3c4d5e6f7a8b"},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"status":{"type":"string","enum":["open","acknowledged","resolved","wont_fix"],"description":"Existing v2 workflow enum retained for response compatibility. Scan projections currently emit open only; do not infer acknowledgement, resolution, or fix verification from a later run."},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"confidence":{"type":"string","enum":["high","medium","low"]},"title":{"type":"string"},"detail":{"type":"string"},"evidence":{"type":"array","items":{"type":"object","required":["type","summary"],"properties":{"type":{"type":"string","enum":["page","file","check"]},"url":{"type":"string"},"summary":{"type":"string"}}}},"affectedUrls":{"type":"array","items":{"type":"string"}},"remediation":{"type":"string"},"agentActions":{"type":"array","items":{"type":"object","required":["type","description"],"properties":{"type":{"type":"string","enum":["remediation"]},"description":{"type":"string"}}}},"humanUrl":{"type":"string","description":"Human-readable dashboard view of this run."},"source":{"type":"object","properties":{"scanMode":{"type":["string","null"]},"model":{"type":["string","null"]}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"stage":{"type":"string","enum":["find","trust","act","measure","improve"],"description":"Marketing Signal funnel stage (Marketing Signal findings only)."}}},"AgentReportContext":{"type":"object","description":"Agent result contract v2 report context. Bounded orientation payload to read before paginating findings.","required":["schemaVersion","product","runId","projectId","url","score","scoreLabel","execSummary","severityCounts","findingsTotal","topFindings","foundation","pagesCrawled","scanMode","model","costUsd","createdAt","completedAt","humanUrl"],"properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["ai_readiness"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"url":{"type":"string","format":"uri"},"score":{"type":"integer","minimum":0,"maximum":100},"scoreStatus":{"type":"string","enum":["unverified"],"description":"Present when source-only page evidence cannot support a score claim."},"scoreLabel":{"type":"string","example":"Needs work"},"execSummary":{"type":"string"},"severityCounts":{"type":"object","required":["critical","high","medium","low","info"],"properties":{"critical":{"type":"integer","minimum":0},"high":{"type":"integer","minimum":0},"medium":{"type":"integer","minimum":0},"low":{"type":"integer","minimum":0},"info":{"type":"integer","minimum":0}}},"findingsTotal":{"type":"integer","minimum":0},"topFindings":{"type":"array","maxItems":10,"items":{"type":"object","required":["findingId","severity","category","title","remediation","affectedUrls"],"properties":{"findingId":{"type":"string","example":"f_1a2b3c4d5e6f7a8b"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"title":{"type":"string"},"remediation":{"type":"string"},"affectedUrls":{"type":"array","items":{"type":"string"}}}}},"foundation":{"type":"object","required":["sitemap","robotsTxt","llmsTxt"],"properties":{"sitemap":{"type":"object","required":["present","notes"],"properties":{"present":{"type":"boolean"},"notes":{"type":"string"}}},"robotsTxt":{"type":"object","required":["present","notes"],"properties":{"present":{"type":"boolean"},"notes":{"type":"string"}}},"llmsTxt":{"type":"object","required":["present","notes"],"properties":{"present":{"type":"boolean"},"notes":{"type":"string"}}}}},"checks":{"type":"object","description":"Structural check ledger for runs created after the ledger shipped. pass/fail/info/unverified summarize rows.","required":["pass","fail","info","unverified","rows"],"properties":{"pass":{"type":"integer","minimum":0},"fail":{"type":"integer","minimum":0},"info":{"type":"integer","minimum":0},"unverified":{"type":"integer","minimum":0},"rows":{"type":"array","items":{"type":"object","description":"One structural probe row from the AI-readiness check ledger. info rows are emerging standards; unverified rows need rendered evidence. Neither is score-penalizing.","required":["id","label","category","status","detail"],"properties":{"id":{"type":"string","example":"mcp-server-card"},"label":{"type":"string","example":"MCP server card"},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"status":{"type":"string","enum":["pass","fail","info","unverified"]},"detail":{"type":"string","example":"Not detected."}}}}}},"pagesCrawled":{"type":"integer","minimum":0},"scanMode":{"type":["string","null"]},"model":{"type":["string","null"]},"costUsd":{"type":"number","minimum":0},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"humanUrl":{"type":"string","description":"Human-readable dashboard view of this exact run."}}},"MarketingReportContext":{"type":"object","description":"Marketing Signal report context (product=marketing_signal). Stage scores replace the AI-Readiness foundation block; sourceCoverage names the evidence base (public_only until connected integrations launch).","required":["schemaVersion","product","runId","projectId","url","score","scoreLabel","execSummary","severityCounts","findingsTotal","stageScores","sourceCoverage","connectedSources","templatesAudited","topFindings","pagesCrawled","scanMode","model","costUsd","createdAt","completedAt","humanUrl"],"properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["marketing_signal"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"url":{"type":"string","format":"uri"},"score":{"type":"integer","minimum":0,"maximum":100},"scoreStatus":{"type":"string","enum":["unverified"],"description":"Present when any Marketing funnel stage needs rendered verification and the numeric fallback is non-authoritative."},"scoreLabel":{"type":"string","example":"Good"},"execSummary":{"type":"string"},"severityCounts":{"type":"object","required":["critical","high","medium","low","info"],"properties":{"critical":{"type":"integer","minimum":0},"high":{"type":"integer","minimum":0},"medium":{"type":"integer","minimum":0},"low":{"type":"integer","minimum":0},"info":{"type":"integer","minimum":0}}},"findingsTotal":{"type":"integer","minimum":0},"stageScores":{"type":"array","description":"The five funnel stages (find/trust/act/measure/improve), each with a canonical 0-100 score, presentation status, and check tallies. Unverified preserves the numeric fallback without claiming verified reporting. The overall score blends stages at weights 20/20/25/25/10.","items":{"type":"object","required":["stage","status","score","checks_pass","checks_fail","finding_count","top_finding","confidence"],"properties":{"stage":{"type":"string","enum":["find","trust","act","measure","improve"],"description":"Marketing Signal funnel stage (Marketing Signal findings only)."},"status":{"type":"string","enum":["scored","unverified"],"description":"unverified means public HTML lacks enough source evidence for this funnel stage, including runtime analytics, metadata, conversion, and trust evidence on a client-rendered page."},"score":{"type":"integer","minimum":0,"maximum":100},"checks_pass":{"type":"integer","minimum":0},"checks_fail":{"type":"integer","minimum":0},"finding_count":{"type":"integer","minimum":0},"top_finding":{"type":["string","null"]},"confidence":{"type":"string","enum":["high","medium","low"],"description":"measure is capped at medium under public_only coverage: HTML proves a tag exists, never that the account behind it is configured correctly."}}}},"sourceCoverage":{"type":"string","enum":["public_only","connected"],"description":"Evidence base for this run. public_only = HTML-visible public signals."},"connectedSources":{"type":"array","items":{"type":"object","required":["provider","account_label","last_synced_at","freshness"],"properties":{"provider":{"type":"string"},"account_label":{"type":"string"},"last_synced_at":{"type":["string","null"],"format":"date-time"},"freshness":{"type":"string","enum":["fresh","stale","error"]}}}},"templatesAudited":{"type":"integer","minimum":0},"topFindings":{"type":"array","maxItems":10,"items":{"type":"object","required":["findingId","severity","category","stage","title","remediation","affectedUrls"],"properties":{"findingId":{"type":"string","example":"f_1a2b3c4d5e6f7a8b"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"stage":{"type":"string","enum":["find","trust","act","measure","improve"],"description":"Marketing Signal funnel stage (Marketing Signal findings only)."},"title":{"type":"string"},"remediation":{"type":"string"},"affectedUrls":{"type":"array","items":{"type":"string"}}}}},"checks":{"type":"object","description":"Marketing check ledger summary (pass/fail/info/unverified) + rows.","required":["pass","fail","info","unverified","rows"],"properties":{"pass":{"type":"integer","minimum":0},"fail":{"type":"integer","minimum":0},"info":{"type":"integer","minimum":0},"unverified":{"type":"integer","minimum":0},"rows":{"type":"array","items":{"type":"object","description":"One structural probe row from the AI-readiness check ledger. info rows are emerging standards; unverified rows need rendered evidence. Neither is score-penalizing.","required":["id","label","category","status","detail"],"properties":{"id":{"type":"string","example":"mcp-server-card"},"label":{"type":"string","example":"MCP server card"},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"status":{"type":"string","enum":["pass","fail","info","unverified"]},"detail":{"type":"string","example":"Not detected."}}}}}},"pagesCrawled":{"type":"integer","minimum":0},"scanMode":{"type":["string","null"],"example":"paid_marketing_signal"},"model":{"type":["string","null"]},"costUsd":{"type":"number","minimum":0},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"humanUrl":{"type":"string","description":"Human-readable Marketing dashboard view of this exact run."}}},"WebsiteSecurityReportContext":{"type":"object","description":"Website Security report context (product=website_security). Includes the public-surface scope disclaimer, pillar rollup, deterministic check ledger, and bounded top findings.","required":["schemaVersion","product","runId","projectId","url","score","scoreLabel","execSummary","severityCounts","findingsTotal","topFindings","scope","pillars","checks","pagesScanned","scanMode","model","costUsd","createdAt","completedAt","humanUrl"],"properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["website_security"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"url":{"type":"string","format":"uri"},"score":{"type":"integer","minimum":0,"maximum":100},"scoreStatus":{"type":"string","enum":["unverified"],"description":"Present when source-only evidence cannot support a numeric Website Security score."},"scoreLabel":{"type":"string","example":"Managed"},"execSummary":{"type":"string"},"severityCounts":{"type":"object","required":["critical","high","medium","low","info"],"properties":{"critical":{"type":"integer","minimum":0},"high":{"type":"integer","minimum":0},"medium":{"type":"integer","minimum":0},"low":{"type":"integer","minimum":0},"info":{"type":"integer","minimum":0}}},"findingsTotal":{"type":"integer","minimum":0},"topFindings":{"type":"array","maxItems":10,"items":{"type":"object","required":["findingId","severity","category","pillar","title","remediation","affectedUrls"],"properties":{"findingId":{"type":"string","example":"f_1a2b3c4d5e6f7a8b"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"category":{"type":"string","enum":["security"]},"pillar":{"type":"string","enum":["browser_defenses","transport_trust","dns_email_trust","cookies_sessions","exposure_reputation"]},"title":{"type":"string"},"remediation":{"type":"string"},"affectedUrls":{"type":"array","items":{"type":"string"}}}}},"scope":{"type":"object","required":["label","disclaimer","pagesScanned"],"properties":{"label":{"type":"string"},"disclaimer":{"type":"string"},"pagesScanned":{"type":"integer","minimum":0}}},"pillars":{"type":"array","items":{"type":"object","required":["key","label","score","weight","pass","fail"],"properties":{"key":{"type":"string","enum":["browser_defenses","transport_trust","dns_email_trust","cookies_sessions","exposure_reputation"]},"label":{"type":"string"},"score":{"type":["integer","null"],"minimum":0,"maximum":100,"description":"Null when the pillar has only unverified runtime-dependent checks."},"weight":{"type":"number","minimum":0,"maximum":100},"pass":{"type":"integer","minimum":0},"fail":{"type":"integer","minimum":0}}}},"checks":{"type":"array","items":{"type":"object","required":["id","label","pillar","status","severity","evidence","recommendation"],"properties":{"id":{"type":"string"},"label":{"type":"string"},"pillar":{"type":"string","enum":["browser_defenses","transport_trust","dns_email_trust","cookies_sessions","exposure_reputation"]},"status":{"type":"string","enum":["pass","fail","info","unverified"]},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"evidence":{"type":"string"},"recommendation":{"type":"string"}}}},"tls":{"type":"object","required":["valid"],"properties":{"valid":{"type":"boolean"},"issuer":{"type":"string"},"subject":{"type":"string"},"validTo":{"type":"string","format":"date-time"},"daysUntilExpiry":{"type":"number"},"error":{"type":"string"}}},"dns":{"type":"object","required":["hasMx","hasSpf","hasDmarc","hasCaa"],"properties":{"hasMx":{"type":"boolean"},"hasSpf":{"type":"boolean"},"hasDmarc":{"type":"boolean"},"hasCaa":{"type":"boolean"}}},"pagesScanned":{"type":"integer","minimum":0},"scanMode":{"type":["string","null"],"example":"paid_website_security"},"model":{"type":["string","null"]},"costUsd":{"type":"number","minimum":0},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"humanUrl":{"type":"string","description":"Human-readable Security dashboard view of this exact run."}}},"IntegrationStatus":{"type":"object","description":"One connected-signal provider and its per-project status. Until the hosted OAuth broker launches, every provider reports connected=false with phase=planned.","required":["provider","label","phase","access","connected"],"properties":{"provider":{"type":"string","enum":["google_analytics","search_console","google_tag_manager","google_ads","meta_ads","linkedin_ads","hubspot"]},"label":{"type":"string","example":"Google Analytics 4"},"phase":{"type":"string","enum":["planned","beta","available"]},"access":{"type":"string","enum":["read_only"]},"connected":{"type":"boolean"},"readScopeSummary":{"type":"string"},"valueSummary":{"type":"string"}}},"Run":{"type":"object","description":"Run status + summary. score/severityCounts are null until status=completed. score is also null when scoreStatus=unverified because source-only evidence cannot support a numeric claim.","properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["ai_readiness","marketing_signal","website_security"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"status":{"type":"string","enum":["pending","running","completed","failed","failed_auto_credit","refunded"]},"progressPct":{"type":"integer","minimum":0,"maximum":100},"currentStep":{"type":["string","null"]},"url":{"type":"string"},"scanMode":{"type":["string","null"]},"model":{"type":["string","null"]},"costUsd":{"type":"number"},"error":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"score":{"type":["integer","null"],"minimum":0,"maximum":100},"scoreStatus":{"type":["string","null"],"enum":["unverified",null],"description":"unverified when source-only page evidence needs rendered verification."},"severityCounts":{"type":["object","null"],"additionalProperties":{"type":"integer"}},"findingsTotal":{"type":["integer","null"]},"coverage":{"type":["object","null"],"description":"Present for a local on-page scan (CLI `scan local`): { mode: 'local_on_page', notEvaluated: [...] } lists the checks not run (DNS/TLS/redirects/foundation files/email auth/response-header security). Null for a normal full scan.","properties":{"mode":{"type":"string","enum":["local_on_page"]},"notEvaluated":{"type":"array","items":{"type":"string"}}}},"humanUrl":{"type":"string"},"links":{"type":"object","properties":{"self":{"type":"string"},"findings":{"type":"string"},"report":{"type":"string"}}}}},"WebhookRunEvent":{"type":"object","description":"Outbound HMAC-signed event envelope. x-index365-signature is t=<unix>,v1=<hmac-sha256 of '<t>.<body>'>; verify v1 against the raw body before processing.","required":["id","type","createdAt","data"],"properties":{"id":{"type":"string","example":"evt_2b0d6297b1494d6d8d60d94b3d41bb5c"},"type":{"type":"string","enum":["run.completed","run.failed"],"example":"run.completed"},"createdAt":{"type":"string","format":"date-time"},"data":{"type":"object","required":["runId","projectId","status","url","score","scoreStatus","severityCounts","findingsTotal","error","humanUrl","apiUrl"],"properties":{"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"status":{"type":"string","enum":["completed","failed"]},"url":{"type":"string","format":"uri"},"score":{"type":["integer","null"],"minimum":0,"maximum":100},"scoreStatus":{"type":["string","null"],"enum":["unverified",null],"description":"unverified means source-only evidence cannot support a numeric score claim, so score is null."},"severityCounts":{"type":["object","null"],"additionalProperties":{"type":"integer"}},"findingsTotal":{"type":["integer","null"]},"error":{"type":["string","null"]},"humanUrl":{"type":"string","format":"uri"},"apiUrl":{"type":"string","format":"uri"}}}},"example":{"id":"evt_2b0d6297b1494d6d8d60d94b3d41bb5c","type":"run.completed","createdAt":"2026-08-13T19:58:00.000Z","data":{"runId":"b59e4634-0d9e-4a0f-a9b0-3f2a34f21c8d","projectId":"a3a6036a-9ba6-47dc-8f22-085454121895","status":"completed","url":"https://acme.test/","score":null,"scoreStatus":"unverified","severityCounts":{"critical":0,"high":0,"medium":0,"low":0,"info":3},"findingsTotal":0,"error":null,"humanUrl":"https://index365.co/dashboard/project/a3a6036a-9ba6-47dc-8f22-085454121895/audits/ai-readiness","apiUrl":"https://index365.co/api/v1/runs/b59e4634-0d9e-4a0f-a9b0-3f2a34f21c8d"}}}}},"webhooks":{"run.completed":{"post":{"summary":"Run completion delivery","description":"Delivered to each subscribed endpoint. x-index365-signature is t=<unix>,v1=<hmac-sha256 of '<t>.<body>'>; verify v1 against the raw body, reject timestamps older than five minutes, then use id or x-index365-event-id for idempotency.","parameters":[{"name":"x-index365-event","in":"header","required":true,"schema":{"type":"string","enum":["run.completed","run.failed"]}},{"name":"x-index365-event-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-index365-signature","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Outbound HMAC-signed event envelope. x-index365-signature is t=<unix>,v1=<hmac-sha256 of '<t>.<body>'>; verify v1 against the raw body before processing.","required":["id","type","createdAt","data"],"properties":{"id":{"type":"string","example":"evt_2b0d6297b1494d6d8d60d94b3d41bb5c"},"type":{"type":"string","enum":["run.completed","run.failed"],"example":"run.completed"},"createdAt":{"type":"string","format":"date-time"},"data":{"type":"object","required":["runId","projectId","status","url","score","scoreStatus","severityCounts","findingsTotal","error","humanUrl","apiUrl"],"properties":{"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"status":{"type":"string","enum":["completed","failed"]},"url":{"type":"string","format":"uri"},"score":{"type":["integer","null"],"minimum":0,"maximum":100},"scoreStatus":{"type":["string","null"],"enum":["unverified",null],"description":"unverified means source-only evidence cannot support a numeric score claim, so score is null."},"severityCounts":{"type":["object","null"],"additionalProperties":{"type":"integer"}},"findingsTotal":{"type":["integer","null"]},"error":{"type":["string","null"]},"humanUrl":{"type":"string","format":"uri"},"apiUrl":{"type":"string","format":"uri"}}}},"example":{"id":"evt_2b0d6297b1494d6d8d60d94b3d41bb5c","type":"run.completed","createdAt":"2026-08-13T19:58:00.000Z","data":{"runId":"b59e4634-0d9e-4a0f-a9b0-3f2a34f21c8d","projectId":"a3a6036a-9ba6-47dc-8f22-085454121895","status":"completed","url":"https://acme.test/","score":null,"scoreStatus":"unverified","severityCounts":{"critical":0,"high":0,"medium":0,"low":0,"info":3},"findingsTotal":0,"error":null,"humanUrl":"https://index365.co/dashboard/project/a3a6036a-9ba6-47dc-8f22-085454121895/audits/ai-readiness","apiUrl":"https://index365.co/api/v1/runs/b59e4634-0d9e-4a0f-a9b0-3f2a34f21c8d"}}}}}},"responses":{"200":{"description":"Receiver acknowledged the delivery."}}}}},"paths":{"/api/v1/me":{"get":{"operationId":"get_key_context","tags":["introspection"],"summary":"Introspect the calling key","description":"Use first in any session to confirm auth works and learn the key's org, project pin, scopes, and contract version. Works with any valid key regardless of scopes. Also carries the account snapshot behind the CLI status card: `plan` (the org's plan tier, e.g. pro or pro_plus; null on the Free plan) and `credits` ({ remaining, monthlyIncluded }; null only when the balance could not be read). Both are optional, best-effort fields; a billing-read failure never fails this endpoint.","responses":{"200":{"description":"Key context.","content":{"application/json":{"example":{"keyPrefix":"i365_a1b2c3d","keyName":"Default","organizationId":"5b8f6f3a-0000-0000-0000-000000000000","organizationName":"Acme","organizationSlug":"acme","projectId":null,"scopes":["projects:read","projects:write","projects:delete","runs:read","runs:write","findings:read","reports:read"],"plan":"pro","credits":{"remaining":80,"monthlyIncluded":100},"apiVersion":"v1","contractVersion":2,"latestCliVersion":"1.1.0","creditCosts":{"ai_readiness":10,"marketing":10,"website_security":10}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/cli/token":{"post":{"operationId":"exchange_cli_authorization_code","tags":["authentication"],"summary":"Exchange a CLI authorization code for a key","description":"Keyless second leg of `index365 login --web`. Swaps the single-use PKCE authorization code (minted on the dashboard consent screen) plus the PKCE code_verifier for a freshly minted, scoped API key. Unauthenticated by design (the client has no key yet); the code is single-use, short-lived, loopback-bound, and PKCE-S256-bound. Not for manual use - the dashboard API Keys page is how humans create keys.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["code","code_verifier","redirect_uri"],"properties":{"code":{"type":"string","description":"Single-use authorization code from the loopback callback."},"code_verifier":{"type":"string","description":"PKCE verifier whose S256 hash is the stored code_challenge."},"redirect_uri":{"type":"string","description":"The exact loopback redirect_uri the CLI registered."}}}}}},"responses":{"201":{"description":"Credential issued. The secret is returned exactly once.","content":{"application/json":{"example":{"secret":"i365_a1b2c3d4e5f6...","keyPrefix":"i365_a1b2c3d","keyName":"index365 CLI on host","scopes":["projects:read","runs:write"],"organizationId":"5b8f6f3a-0000-0000-0000-000000000000","organizationSlug":"acme"}}}},"400":{"description":"invalid_request (missing fields) | invalid_grant (unknown/expired/used/mismatched code).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"500":{"description":"internal_error: the credential could not be issued.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"503":{"description":"key_encryption_unavailable | service_unavailable.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/projects":{"get":{"operationId":"list_projects","tags":["projects"],"summary":"List projects","description":"Cursor-paginated projects in the key's organization. Omitted status excludes archived projects. Pass active, paused, archived, or all to select a lifecycle view; use status=archived to find a project to restore.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Page size (max 100)."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from the previous page's pagination.nextCursor."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["active","paused","archived","all"]},"description":"Omitted status excludes archived projects. active, paused, and archived are exact filters; all removes the lifecycle filter."}],"responses":{"200":{"description":"Project page.","content":{"application/json":{"example":{"projects":[{"projectId":"1f2e3d4c-0000-0000-0000-000000000000","name":"Acme marketing site","domain":"acme.com","slug":"acme-com","status":"active","createdAt":"2026-06-01T12:00:00Z","updatedAt":"2026-06-01T12:00:00Z"}],"pagination":{"nextCursor":null,"limit":20}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}},"post":{"operationId":"create_project","tags":["projects"],"summary":"Create a project","description":"Create a domain-anchored project in the key's organization. Requires projects:write. Idempotent by domain: re-creating an active or paused domain returns the existing project. Re-creating an archived domain restores the original project row to active with its history and keys intact, returning restored=true. A brand-new project returns 201. Project-pinned keys cannot create.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string","minLength":3,"maxLength":253},"name":{"type":"string","maxLength":100}}},"example":{"domain":"acme.com","name":"Acme marketing site"}}}},"responses":{"200":{"description":"Idempotent: a project for that domain already existed (idempotent=true). An archived project was reactivated when restored=true."},"201":{"description":"Project created.","content":{"application/json":{"example":{"projectId":"1f2e3d4c-0000-0000-0000-000000000000","name":"Acme marketing site","domain":"acme.com","slug":"acme-com","status":"active","createdAt":"2026-06-01T12:00:00Z","updatedAt":"2026-06-01T12:00:00Z"}}}},"400":{"description":"invalid_json | invalid_domain.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"insufficient_scope | project_scoped_key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"409":{"description":"project_limit_reached | project_exists.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/projects/{projectId}":{"get":{"operationId":"get_project","tags":["projects"],"summary":"Get one project","description":"Fetch a single project by id (scoped to the key's org).","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Project."},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}},"patch":{"operationId":"restore_project","tags":["projects"],"summary":"Restore a project","description":"Restore an archived project to active status while preserving its id, scan history, and API keys. Requires projects:write. The strict request body is exactly { status: 'active' }; retries are state-idempotent.","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["active"]}},"additionalProperties":false},"example":{"status":"active"}}}},"responses":{"200":{"description":"Project is active. restored=true identifies a completed archived-to-active transition; restored=false and idempotent=true identifies an already-active retry.","content":{"application/json":{"example":{"projectId":"1f2e3d4c-0000-0000-0000-000000000000","name":"Acme marketing site","domain":"acme.com","slug":"acme-com","status":"active","createdAt":"2026-06-01T12:00:00Z","updatedAt":"2026-07-14T12:00:00Z","restored":true,"idempotent":false}}}},"400":{"description":"invalid_json | validation_failed.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"409":{"description":"project_not_archived: the project is paused or otherwise not archived, so no state mutation occurred.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}},"delete":{"operationId":"delete_project","tags":["projects"],"summary":"Archive a project (legacy DELETE route)","description":"Compatibility DELETE route that archives a project through a reversible lifecycle. The project leaves active lists and cannot start new runs, while its history and API keys remain available for restore_project. Requires projects:delete. Read first, then send confirm set to the project's exact domain.","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"confirm","in":"query","required":false,"schema":{"type":"string"},"description":"The project's exact domain. Required (here or in a JSON body) to authorize the archive."}],"responses":{"200":{"description":"Project archived. The response explicitly confirms no hard delete occurred.","content":{"application/json":{"example":{"ok":true,"projectId":"1f2e3d4c-0000-0000-0000-000000000000","archived":true,"deleted":false}}}},"400":{"description":"confirmation_required | confirmation_mismatch.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"insufficient_scope | project_scoped_key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/projects/{projectId}/marketing/report":{"get":{"operationId":"get_marketing_report","tags":["reports"],"summary":"Get the latest Marketing Signal report for a project","description":"Project-scoped convenience over get_report_context: returns the latest COMPLETED Marketing Signal run's report (stage scores, source coverage, top findings) without listing runs first. 404 error.code=no_marketing_run means no marketing audit has completed yet; start one with start_audit scanMode=paid_marketing_signal.","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Marketing Signal report context.","content":{"application/json":{"schema":{"type":"object","description":"Marketing Signal report context (product=marketing_signal). Stage scores replace the AI-Readiness foundation block; sourceCoverage names the evidence base (public_only until connected integrations launch).","required":["schemaVersion","product","runId","projectId","url","score","scoreLabel","execSummary","severityCounts","findingsTotal","stageScores","sourceCoverage","connectedSources","templatesAudited","topFindings","pagesCrawled","scanMode","model","costUsd","createdAt","completedAt","humanUrl"],"properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["marketing_signal"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"url":{"type":"string","format":"uri"},"score":{"type":"integer","minimum":0,"maximum":100},"scoreStatus":{"type":"string","enum":["unverified"],"description":"Present when any Marketing funnel stage needs rendered verification and the numeric fallback is non-authoritative."},"scoreLabel":{"type":"string","example":"Good"},"execSummary":{"type":"string"},"severityCounts":{"type":"object","required":["critical","high","medium","low","info"],"properties":{"critical":{"type":"integer","minimum":0},"high":{"type":"integer","minimum":0},"medium":{"type":"integer","minimum":0},"low":{"type":"integer","minimum":0},"info":{"type":"integer","minimum":0}}},"findingsTotal":{"type":"integer","minimum":0},"stageScores":{"type":"array","description":"The five funnel stages (find/trust/act/measure/improve), each with a canonical 0-100 score, presentation status, and check tallies. Unverified preserves the numeric fallback without claiming verified reporting. The overall score blends stages at weights 20/20/25/25/10.","items":{"type":"object","required":["stage","status","score","checks_pass","checks_fail","finding_count","top_finding","confidence"],"properties":{"stage":{"type":"string","enum":["find","trust","act","measure","improve"],"description":"Marketing Signal funnel stage (Marketing Signal findings only)."},"status":{"type":"string","enum":["scored","unverified"],"description":"unverified means public HTML lacks enough source evidence for this funnel stage, including runtime analytics, metadata, conversion, and trust evidence on a client-rendered page."},"score":{"type":"integer","minimum":0,"maximum":100},"checks_pass":{"type":"integer","minimum":0},"checks_fail":{"type":"integer","minimum":0},"finding_count":{"type":"integer","minimum":0},"top_finding":{"type":["string","null"]},"confidence":{"type":"string","enum":["high","medium","low"],"description":"measure is capped at medium under public_only coverage: HTML proves a tag exists, never that the account behind it is configured correctly."}}}},"sourceCoverage":{"type":"string","enum":["public_only","connected"],"description":"Evidence base for this run. public_only = HTML-visible public signals."},"connectedSources":{"type":"array","items":{"type":"object","required":["provider","account_label","last_synced_at","freshness"],"properties":{"provider":{"type":"string"},"account_label":{"type":"string"},"last_synced_at":{"type":["string","null"],"format":"date-time"},"freshness":{"type":"string","enum":["fresh","stale","error"]}}}},"templatesAudited":{"type":"integer","minimum":0},"topFindings":{"type":"array","maxItems":10,"items":{"type":"object","required":["findingId","severity","category","stage","title","remediation","affectedUrls"],"properties":{"findingId":{"type":"string","example":"f_1a2b3c4d5e6f7a8b"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"stage":{"type":"string","enum":["find","trust","act","measure","improve"],"description":"Marketing Signal funnel stage (Marketing Signal findings only)."},"title":{"type":"string"},"remediation":{"type":"string"},"affectedUrls":{"type":"array","items":{"type":"string"}}}}},"checks":{"type":"object","description":"Marketing check ledger summary (pass/fail/info/unverified) + rows.","required":["pass","fail","info","unverified","rows"],"properties":{"pass":{"type":"integer","minimum":0},"fail":{"type":"integer","minimum":0},"info":{"type":"integer","minimum":0},"unverified":{"type":"integer","minimum":0},"rows":{"type":"array","items":{"type":"object","description":"One structural probe row from the AI-readiness check ledger. info rows are emerging standards; unverified rows need rendered evidence. Neither is score-penalizing.","required":["id","label","category","status","detail"],"properties":{"id":{"type":"string","example":"mcp-server-card"},"label":{"type":"string","example":"MCP server card"},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"status":{"type":"string","enum":["pass","fail","info","unverified"]},"detail":{"type":"string","example":"Not detected."}}}}}},"pagesCrawled":{"type":"integer","minimum":0},"scanMode":{"type":["string","null"],"example":"paid_marketing_signal"},"model":{"type":["string","null"]},"costUsd":{"type":"number","minimum":0},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"humanUrl":{"type":"string","description":"Human-readable Marketing dashboard view of this exact run."}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"not_found | no_marketing_run | results_unavailable.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/projects/{projectId}/integrations":{"get":{"operationId":"list_integrations","tags":["projects"],"summary":"List connected-signal integrations for a project","description":"Provider registry + per-project connection status for connected signals (GA4, Search Console, Tag Manager, ads, CRM). Until the hosted integration layer launches every provider reports connected=false with phase=planned; this endpoint exists so agents can discover the surface without guessing.","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Integration statuses.","content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","format":"uuid"},"integrations":{"type":"array","items":{"type":"object","description":"One connected-signal provider and its per-project status. Until the hosted OAuth broker launches, every provider reports connected=false with phase=planned.","required":["provider","label","phase","access","connected"],"properties":{"provider":{"type":"string","enum":["google_analytics","search_console","google_tag_manager","google_ads","meta_ads","linkedin_ads","hubspot"]},"label":{"type":"string","example":"Google Analytics 4"},"phase":{"type":"string","enum":["planned","beta","available"]},"access":{"type":"string","enum":["read_only"]},"connected":{"type":"boolean"},"readScopeSummary":{"type":"string"},"valueSummary":{"type":"string"}}}},"note":{"type":"string"}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/projects/{projectId}/signals":{"get":{"operationId":"list_connected_signals","tags":["projects"],"summary":"List connected-source signal rows for a project","description":"Normalized signal rows imported from connected sources. Stable surface for the integration layer: under public_only coverage (current state) the list is empty and sourceCoverage says so explicitly.","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Signal rows + source coverage.","content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","format":"uuid"},"sourceCoverage":{"type":"string","enum":["public_only","connected"]},"connectedSources":{"type":"array","items":{"type":"object"}},"signals":{"type":"array","items":{"type":"object"}},"note":{"type":"string"}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/runs":{"get":{"operationId":"list_runs","tags":["runs"],"summary":"List audit runs","description":"Cursor-paginated runs, newest first. Filter with projectId and status. List items are compact but carry score state (completed runs only) and finishedAt, so ranking or picking the latest run never needs per-run fetches. score is null with scoreStatus=unverified when source-only evidence needs rendered verification; call get_run for links and full detail.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Page size (max 100)."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from the previous page's pagination.nextCursor."},{"name":"projectId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","running","completed","failed","failed_auto_credit","refunded"]}}],"responses":{"200":{"description":"Run page.","content":{"application/json":{"schema":{"type":"object","required":["runs","pagination"],"properties":{"runs":{"type":"array","items":{"type":"object","required":["runId","projectId","product","status","progressPct","url","score","scoreStatus","scanMode","createdAt","completedAt","finishedAt"],"properties":{"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"product":{"type":"string","enum":["ai_readiness","marketing_signal","website_security"]},"status":{"type":"string","enum":["pending","running","completed","failed","failed_auto_credit","refunded"]},"progressPct":{"type":"integer","minimum":0,"maximum":100},"url":{"type":"string"},"score":{"type":["integer","null"],"minimum":0,"maximum":100},"scoreStatus":{"type":["string","null"],"enum":["unverified",null],"description":"unverified when source-only page evidence needs rendered verification."},"scanMode":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"finishedAt":{"type":["string","null"],"format":"date-time"}}}},"pagination":{"type":"object","required":["nextCursor","limit"],"properties":{"nextCursor":{"type":["string","null"]},"limit":{"type":"integer","minimum":1,"maximum":100}}}}}}}},"400":{"description":"Unknown status filter (error.code=validation_failed).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}},"post":{"operationId":"start_audit","tags":["runs"],"summary":"Start a paid scan","description":"Starts a supported paid scan and returns 202 with the run immediately. Pass projectId for an existing project, or omit it with an absolute URL to reuse or create that URL's canonical-domain project in the key's organization. scanMode defaults to paid_ai_readiness; use paid_marketing_signal for Marketing Signal or paid_website_security for the deterministic public-surface security scan. Spends org credits (10/run); requires the runs:write scope and an active paid plan. Poll get_run for completion. Send an Idempotency-Key header so retries never double-spend. Single-flight is per product per project.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Replaying the same key returns the original run (200) instead of creating a new one."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","anyOf":[{"required":["projectId"]},{"required":["url"]}],"additionalProperties":false,"properties":{"projectId":{"type":"string","format":"uuid","description":"Existing project. Omit with an absolute URL to auto-create or reuse that domain project."},"scanMode":{"type":"string","enum":["paid_ai_readiness","paid_marketing_signal","paid_website_security"],"default":"paid_ai_readiness"},"url":{"type":"string","minLength":1,"maxLength":2048,"description":"The single page this run audits. With projectId, use an absolute same-domain URL or root-relative path like '/pricing'; omit it for the project homepage. Without projectId, use an absolute public-domain URL and its normalized domain project is created or reused."},"idempotencyKey":{"type":"string","maxLength":255}}},"example":{"scanMode":"paid_ai_readiness","url":"https://yoursite.com/pricing"}}}},"responses":{"200":{"description":"Idempotent replay of an existing run (idempotentReplay=true).","content":{"application/json":{"schema":{"type":"object","description":"Run status + summary. score/severityCounts are null until status=completed. score is also null when scoreStatus=unverified because source-only evidence cannot support a numeric claim.","properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["ai_readiness","marketing_signal","website_security"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"status":{"type":"string","enum":["pending","running","completed","failed","failed_auto_credit","refunded"]},"progressPct":{"type":"integer","minimum":0,"maximum":100},"currentStep":{"type":["string","null"]},"url":{"type":"string"},"scanMode":{"type":["string","null"]},"model":{"type":["string","null"]},"costUsd":{"type":"number"},"error":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"score":{"type":["integer","null"],"minimum":0,"maximum":100},"scoreStatus":{"type":["string","null"],"enum":["unverified",null],"description":"unverified when source-only page evidence needs rendered verification."},"severityCounts":{"type":["object","null"],"additionalProperties":{"type":"integer"}},"findingsTotal":{"type":["integer","null"]},"coverage":{"type":["object","null"],"description":"Present for a local on-page scan (CLI `scan local`): { mode: 'local_on_page', notEvaluated: [...] } lists the checks not run (DNS/TLS/redirects/foundation files/email auth/response-header security). Null for a normal full scan.","properties":{"mode":{"type":"string","enum":["local_on_page"]},"notEvaluated":{"type":"array","items":{"type":"string"}}}},"humanUrl":{"type":"string"},"links":{"type":"object","properties":{"self":{"type":"string"},"findings":{"type":"string"},"report":{"type":"string"}}}}}}}},"202":{"description":"Run accepted and queued.","content":{"application/json":{"schema":{"type":"object","description":"Run status + summary. score/severityCounts are null until status=completed. score is also null when scoreStatus=unverified because source-only evidence cannot support a numeric claim.","properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["ai_readiness","marketing_signal","website_security"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"status":{"type":"string","enum":["pending","running","completed","failed","failed_auto_credit","refunded"]},"progressPct":{"type":"integer","minimum":0,"maximum":100},"currentStep":{"type":["string","null"]},"url":{"type":"string"},"scanMode":{"type":["string","null"]},"model":{"type":["string","null"]},"costUsd":{"type":"number"},"error":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"score":{"type":["integer","null"],"minimum":0,"maximum":100},"scoreStatus":{"type":["string","null"],"enum":["unverified",null],"description":"unverified when source-only page evidence needs rendered verification."},"severityCounts":{"type":["object","null"],"additionalProperties":{"type":"integer"}},"findingsTotal":{"type":["integer","null"]},"coverage":{"type":["object","null"],"description":"Present for a local on-page scan (CLI `scan local`): { mode: 'local_on_page', notEvaluated: [...] } lists the checks not run (DNS/TLS/redirects/foundation files/email auth/response-header security). Null for a normal full scan.","properties":{"mode":{"type":"string","enum":["local_on_page"]},"notEvaluated":{"type":"array","items":{"type":"string"}}}},"humanUrl":{"type":"string"},"links":{"type":"object","properties":{"self":{"type":"string"},"findings":{"type":"string"},"report":{"type":"string"}}}}}}}},"400":{"description":"invalid_json | validation_failed | url_not_same_domain | auto_project_requires_public_domain.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"402":{"description":"no_active_subscription | insufficient_credits.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"insufficient_scope | key_project_mismatch | project_scoped_key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"409":{"description":"run_in_flight: an audit is already running for this project; project_limit_reached when a future project cap is reached.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/runs/analyze-html":{"post":{"operationId":"analyze_local_html","tags":["runs"],"summary":"Score an uploaded local page (local on-page scan)","description":"Scores a page captured on your OWN machine: the `index365 scan local` CLI fetches a localhost/dev URL, then uploads the HTML response (and its response headers) here. The server NEVER fetches the target or any URL inside the HTML, so it scores only on-page AI-Readiness checks read from the uploaded HTML (content/structure, metadata, schema, and answerability). DNS, TLS, redirects, foundation files (robots/sitemap/llms.txt), email auth, and response-header security are NOT evaluated and are listed in coverage.notEvaluated (top-level on the run envelope + report context). v1 supports product=ai_readiness only. Pass projectId for localhost/private captures; omit it for a public-domain capture to auto-create or reuse that domain project. Creates a normal paid run (spends org credits; requires runs:write + an active paid plan) with coverage.mode=local_on_page; idempotency is derived from the page url + its html, so a re-scan after a fix is a new run. Poll get_run for completion.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["capture"],"additionalProperties":false,"properties":{"projectId":{"type":"string","format":"uuid","description":"Existing project. Required for localhost/private capture URLs."},"product":{"type":"string","enum":["ai_readiness"],"default":"ai_readiness","description":"Local scans support ai_readiness only in v1."},"capture":{"type":"object","required":["url","html"],"description":"The page captured locally. The CLI builds this; cookie VALUES are never sent (only flag metadata), and any Set-Cookie or authorization header is stripped server-side before storage.","properties":{"url":{"type":"string","description":"The local URL scanned, e.g. http://localhost:3000/pricing."},"finalUrl":{"type":"string"},"status":{"type":"integer"},"html":{"type":"string","description":"The rendered page HTML (max ~2MB)."},"headers":{"type":"object","additionalProperties":{"type":"string"}},"cookieMeta":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"secure":{"type":"boolean"},"httpOnly":{"type":"boolean"},"sameSite":{"type":"string"}}}}}}}},"example":{"projectId":"1f2e3d4c-0000-0000-0000-000000000000","product":"ai_readiness","capture":{"url":"http://localhost:3000/pricing","status":200,"html":"<!doctype html><html>…</html>"}}}}},"responses":{"200":{"description":"Idempotent replay of an existing run (idempotentReplay=true).","content":{"application/json":{"schema":{"type":"object","description":"Run status + summary. score/severityCounts are null until status=completed. score is also null when scoreStatus=unverified because source-only evidence cannot support a numeric claim.","properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["ai_readiness","marketing_signal","website_security"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"status":{"type":"string","enum":["pending","running","completed","failed","failed_auto_credit","refunded"]},"progressPct":{"type":"integer","minimum":0,"maximum":100},"currentStep":{"type":["string","null"]},"url":{"type":"string"},"scanMode":{"type":["string","null"]},"model":{"type":["string","null"]},"costUsd":{"type":"number"},"error":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"score":{"type":["integer","null"],"minimum":0,"maximum":100},"scoreStatus":{"type":["string","null"],"enum":["unverified",null],"description":"unverified when source-only page evidence needs rendered verification."},"severityCounts":{"type":["object","null"],"additionalProperties":{"type":"integer"}},"findingsTotal":{"type":["integer","null"]},"coverage":{"type":["object","null"],"description":"Present for a local on-page scan (CLI `scan local`): { mode: 'local_on_page', notEvaluated: [...] } lists the checks not run (DNS/TLS/redirects/foundation files/email auth/response-header security). Null for a normal full scan.","properties":{"mode":{"type":"string","enum":["local_on_page"]},"notEvaluated":{"type":"array","items":{"type":"string"}}}},"humanUrl":{"type":"string"},"links":{"type":"object","properties":{"self":{"type":"string"},"findings":{"type":"string"},"report":{"type":"string"}}}}}}}},"202":{"description":"Local scan accepted and queued.","content":{"application/json":{"schema":{"type":"object","description":"Run status + summary. score/severityCounts are null until status=completed. score is also null when scoreStatus=unverified because source-only evidence cannot support a numeric claim.","properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["ai_readiness","marketing_signal","website_security"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"status":{"type":"string","enum":["pending","running","completed","failed","failed_auto_credit","refunded"]},"progressPct":{"type":"integer","minimum":0,"maximum":100},"currentStep":{"type":["string","null"]},"url":{"type":"string"},"scanMode":{"type":["string","null"]},"model":{"type":["string","null"]},"costUsd":{"type":"number"},"error":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"score":{"type":["integer","null"],"minimum":0,"maximum":100},"scoreStatus":{"type":["string","null"],"enum":["unverified",null],"description":"unverified when source-only page evidence needs rendered verification."},"severityCounts":{"type":["object","null"],"additionalProperties":{"type":"integer"}},"findingsTotal":{"type":["integer","null"]},"coverage":{"type":["object","null"],"description":"Present for a local on-page scan (CLI `scan local`): { mode: 'local_on_page', notEvaluated: [...] } lists the checks not run (DNS/TLS/redirects/foundation files/email auth/response-header security). Null for a normal full scan.","properties":{"mode":{"type":"string","enum":["local_on_page"]},"notEvaluated":{"type":"array","items":{"type":"string"}}}},"humanUrl":{"type":"string"},"links":{"type":"object","properties":{"self":{"type":"string"},"findings":{"type":"string"},"report":{"type":"string"}}}}}}}},"400":{"description":"invalid_json | validation_failed | invalid_capture.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"402":{"description":"no_active_subscription | insufficient_credits.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"insufficient_scope | key_project_mismatch.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"409":{"description":"run_in_flight: an audit is already running for this project.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"413":{"description":"capture_too_large: the uploaded HTML exceeds the size cap.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/runs/{runId}":{"get":{"operationId":"get_run","tags":["runs"],"summary":"Get run status + summary","description":"Poll this until status is terminal. Completed runs are immutable and served with a cacheable Cache-Control; in-flight runs are no-store.","parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Run id returned by start_audit or list_runs."}],"responses":{"200":{"description":"Run envelope.","content":{"application/json":{"schema":{"type":"object","description":"Run status + summary. score/severityCounts are null until status=completed. score is also null when scoreStatus=unverified because source-only evidence cannot support a numeric claim.","properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["ai_readiness","marketing_signal","website_security"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"status":{"type":"string","enum":["pending","running","completed","failed","failed_auto_credit","refunded"]},"progressPct":{"type":"integer","minimum":0,"maximum":100},"currentStep":{"type":["string","null"]},"url":{"type":"string"},"scanMode":{"type":["string","null"]},"model":{"type":["string","null"]},"costUsd":{"type":"number"},"error":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"score":{"type":["integer","null"],"minimum":0,"maximum":100},"scoreStatus":{"type":["string","null"],"enum":["unverified",null],"description":"unverified when source-only page evidence needs rendered verification."},"severityCounts":{"type":["object","null"],"additionalProperties":{"type":"integer"}},"findingsTotal":{"type":["integer","null"]},"coverage":{"type":["object","null"],"description":"Present for a local on-page scan (CLI `scan local`): { mode: 'local_on_page', notEvaluated: [...] } lists the checks not run (DNS/TLS/redirects/foundation files/email auth/response-header security). Null for a normal full scan.","properties":{"mode":{"type":"string","enum":["local_on_page"]},"notEvaluated":{"type":"array","items":{"type":"string"}}}},"humanUrl":{"type":"string"},"links":{"type":"object","properties":{"self":{"type":"string"},"findings":{"type":"string"},"report":{"type":"string"}}}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/runs/{runId}/findings":{"get":{"operationId":"list_findings","tags":["findings"],"summary":"List findings (agent contract v2)","description":"Severity-ordered findings with run-scoped ids, evidence, affected URLs, and remediation. Read get_report_context first for orientation, then page through here. Filter with severity/category.","parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Completed run to read findings from."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Page size (max 100)."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from the previous page's pagination.nextCursor."},{"name":"severity","in":"query","required":false,"schema":{"type":"string","enum":["critical","high","medium","low","info"]}},{"name":"category","in":"query","required":false,"schema":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]}},{"name":"stage","in":"query","required":false,"schema":{"type":"string","enum":["find","trust","act","measure","improve"],"description":"Marketing Signal funnel stage (Marketing Signal findings only)."},"description":"Filter Marketing Signal findings by funnel stage."}],"responses":{"200":{"description":"Finding page.","content":{"application/json":{"schema":{"type":"object","properties":{"schemaVersion":{"type":"integer"},"runId":{"type":"string"},"findingsTotal":{"type":"integer"},"findings":{"type":"array","items":{"type":"object","description":"Agent result contract v2 finding. findingId is deterministic and stable for a given run.","required":["findingId","runId","category","status","severity","confidence","title","detail","evidence","affectedUrls","remediation","agentActions","humanUrl","createdAt","updatedAt"],"properties":{"findingId":{"type":"string","example":"f_1a2b3c4d5e6f7a8b"},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"status":{"type":"string","enum":["open","acknowledged","resolved","wont_fix"],"description":"Existing v2 workflow enum retained for response compatibility. Scan projections currently emit open only; do not infer acknowledgement, resolution, or fix verification from a later run."},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"confidence":{"type":"string","enum":["high","medium","low"]},"title":{"type":"string"},"detail":{"type":"string"},"evidence":{"type":"array","items":{"type":"object","required":["type","summary"],"properties":{"type":{"type":"string","enum":["page","file","check"]},"url":{"type":"string"},"summary":{"type":"string"}}}},"affectedUrls":{"type":"array","items":{"type":"string"}},"remediation":{"type":"string"},"agentActions":{"type":"array","items":{"type":"object","required":["type","description"],"properties":{"type":{"type":"string","enum":["remediation"]},"description":{"type":"string"}}}},"humanUrl":{"type":"string","description":"Human-readable dashboard view of this run."},"source":{"type":"object","properties":{"scanMode":{"type":["string","null"]},"model":{"type":["string","null"]}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"stage":{"type":"string","enum":["find","trust","act","measure","improve"],"description":"Marketing Signal funnel stage (Marketing Signal findings only)."}}}},"pagination":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"limit":{"type":"integer"}}}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"409":{"description":"run_not_completed: findings exist only after completion.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/runs/{runId}/findings/{findingId}":{"get":{"operationId":"get_finding","tags":["findings"],"summary":"Get one finding by id","description":"Fetch-by-id detail for a finding surfaced by list_findings.","parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Run the finding belongs to."},{"name":"findingId","in":"path","required":true,"schema":{"type":"string"},"description":"Run-scoped finding id (f_...)."}],"responses":{"200":{"description":"Finding.","content":{"application/json":{"schema":{"type":"object","properties":{"schemaVersion":{"type":"integer"},"finding":{"type":"object","description":"Agent result contract v2 finding. findingId is deterministic and stable for a given run.","required":["findingId","runId","category","status","severity","confidence","title","detail","evidence","affectedUrls","remediation","agentActions","humanUrl","createdAt","updatedAt"],"properties":{"findingId":{"type":"string","example":"f_1a2b3c4d5e6f7a8b"},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"status":{"type":"string","enum":["open","acknowledged","resolved","wont_fix"],"description":"Existing v2 workflow enum retained for response compatibility. Scan projections currently emit open only; do not infer acknowledgement, resolution, or fix verification from a later run."},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"confidence":{"type":"string","enum":["high","medium","low"]},"title":{"type":"string"},"detail":{"type":"string"},"evidence":{"type":"array","items":{"type":"object","required":["type","summary"],"properties":{"type":{"type":"string","enum":["page","file","check"]},"url":{"type":"string"},"summary":{"type":"string"}}}},"affectedUrls":{"type":"array","items":{"type":"string"}},"remediation":{"type":"string"},"agentActions":{"type":"array","items":{"type":"object","required":["type","description"],"properties":{"type":{"type":"string","enum":["remediation"]},"description":{"type":"string"}}}},"humanUrl":{"type":"string","description":"Human-readable dashboard view of this run."},"source":{"type":"object","properties":{"scanMode":{"type":["string","null"]},"model":{"type":["string","null"]}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"stage":{"type":"string","enum":["find","trust","act","measure","improve"],"description":"Marketing Signal funnel stage (Marketing Signal findings only)."}}}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"409":{"description":"run_not_completed: findings exist only after completion.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/runs/{runId}/report":{"get":{"operationId":"get_report_context","tags":["reports"],"summary":"Get the compact agent report context","description":"Bounded orientation payload to read FIRST after a run completes; it is sized to fit agent context budgets. Discriminate on `product`: AI-Readiness serves foundation-file state, Marketing Signal serves stage scores and source coverage, and Website Security serves public-surface scope, pillars, and deterministic checks.","parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Completed run."}],"responses":{"200":{"description":"Product-aware report context.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","description":"Agent result contract v2 report context. Bounded orientation payload to read before paginating findings.","required":["schemaVersion","product","runId","projectId","url","score","scoreLabel","execSummary","severityCounts","findingsTotal","topFindings","foundation","pagesCrawled","scanMode","model","costUsd","createdAt","completedAt","humanUrl"],"properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["ai_readiness"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"url":{"type":"string","format":"uri"},"score":{"type":"integer","minimum":0,"maximum":100},"scoreStatus":{"type":"string","enum":["unverified"],"description":"Present when source-only page evidence cannot support a score claim."},"scoreLabel":{"type":"string","example":"Needs work"},"execSummary":{"type":"string"},"severityCounts":{"type":"object","required":["critical","high","medium","low","info"],"properties":{"critical":{"type":"integer","minimum":0},"high":{"type":"integer","minimum":0},"medium":{"type":"integer","minimum":0},"low":{"type":"integer","minimum":0},"info":{"type":"integer","minimum":0}}},"findingsTotal":{"type":"integer","minimum":0},"topFindings":{"type":"array","maxItems":10,"items":{"type":"object","required":["findingId","severity","category","title","remediation","affectedUrls"],"properties":{"findingId":{"type":"string","example":"f_1a2b3c4d5e6f7a8b"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"title":{"type":"string"},"remediation":{"type":"string"},"affectedUrls":{"type":"array","items":{"type":"string"}}}}},"foundation":{"type":"object","required":["sitemap","robotsTxt","llmsTxt"],"properties":{"sitemap":{"type":"object","required":["present","notes"],"properties":{"present":{"type":"boolean"},"notes":{"type":"string"}}},"robotsTxt":{"type":"object","required":["present","notes"],"properties":{"present":{"type":"boolean"},"notes":{"type":"string"}}},"llmsTxt":{"type":"object","required":["present","notes"],"properties":{"present":{"type":"boolean"},"notes":{"type":"string"}}}}},"checks":{"type":"object","description":"Structural check ledger for runs created after the ledger shipped. pass/fail/info/unverified summarize rows.","required":["pass","fail","info","unverified","rows"],"properties":{"pass":{"type":"integer","minimum":0},"fail":{"type":"integer","minimum":0},"info":{"type":"integer","minimum":0},"unverified":{"type":"integer","minimum":0},"rows":{"type":"array","items":{"type":"object","description":"One structural probe row from the AI-readiness check ledger. info rows are emerging standards; unverified rows need rendered evidence. Neither is score-penalizing.","required":["id","label","category","status","detail"],"properties":{"id":{"type":"string","example":"mcp-server-card"},"label":{"type":"string","example":"MCP server card"},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"status":{"type":"string","enum":["pass","fail","info","unverified"]},"detail":{"type":"string","example":"Not detected."}}}}}},"pagesCrawled":{"type":"integer","minimum":0},"scanMode":{"type":["string","null"]},"model":{"type":["string","null"]},"costUsd":{"type":"number","minimum":0},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"humanUrl":{"type":"string","description":"Human-readable dashboard view of this exact run."}}},{"type":"object","description":"Marketing Signal report context (product=marketing_signal). Stage scores replace the AI-Readiness foundation block; sourceCoverage names the evidence base (public_only until connected integrations launch).","required":["schemaVersion","product","runId","projectId","url","score","scoreLabel","execSummary","severityCounts","findingsTotal","stageScores","sourceCoverage","connectedSources","templatesAudited","topFindings","pagesCrawled","scanMode","model","costUsd","createdAt","completedAt","humanUrl"],"properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["marketing_signal"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"url":{"type":"string","format":"uri"},"score":{"type":"integer","minimum":0,"maximum":100},"scoreStatus":{"type":"string","enum":["unverified"],"description":"Present when any Marketing funnel stage needs rendered verification and the numeric fallback is non-authoritative."},"scoreLabel":{"type":"string","example":"Good"},"execSummary":{"type":"string"},"severityCounts":{"type":"object","required":["critical","high","medium","low","info"],"properties":{"critical":{"type":"integer","minimum":0},"high":{"type":"integer","minimum":0},"medium":{"type":"integer","minimum":0},"low":{"type":"integer","minimum":0},"info":{"type":"integer","minimum":0}}},"findingsTotal":{"type":"integer","minimum":0},"stageScores":{"type":"array","description":"The five funnel stages (find/trust/act/measure/improve), each with a canonical 0-100 score, presentation status, and check tallies. Unverified preserves the numeric fallback without claiming verified reporting. The overall score blends stages at weights 20/20/25/25/10.","items":{"type":"object","required":["stage","status","score","checks_pass","checks_fail","finding_count","top_finding","confidence"],"properties":{"stage":{"type":"string","enum":["find","trust","act","measure","improve"],"description":"Marketing Signal funnel stage (Marketing Signal findings only)."},"status":{"type":"string","enum":["scored","unverified"],"description":"unverified means public HTML lacks enough source evidence for this funnel stage, including runtime analytics, metadata, conversion, and trust evidence on a client-rendered page."},"score":{"type":"integer","minimum":0,"maximum":100},"checks_pass":{"type":"integer","minimum":0},"checks_fail":{"type":"integer","minimum":0},"finding_count":{"type":"integer","minimum":0},"top_finding":{"type":["string","null"]},"confidence":{"type":"string","enum":["high","medium","low"],"description":"measure is capped at medium under public_only coverage: HTML proves a tag exists, never that the account behind it is configured correctly."}}}},"sourceCoverage":{"type":"string","enum":["public_only","connected"],"description":"Evidence base for this run. public_only = HTML-visible public signals."},"connectedSources":{"type":"array","items":{"type":"object","required":["provider","account_label","last_synced_at","freshness"],"properties":{"provider":{"type":"string"},"account_label":{"type":"string"},"last_synced_at":{"type":["string","null"],"format":"date-time"},"freshness":{"type":"string","enum":["fresh","stale","error"]}}}},"templatesAudited":{"type":"integer","minimum":0},"topFindings":{"type":"array","maxItems":10,"items":{"type":"object","required":["findingId","severity","category","stage","title","remediation","affectedUrls"],"properties":{"findingId":{"type":"string","example":"f_1a2b3c4d5e6f7a8b"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"stage":{"type":"string","enum":["find","trust","act","measure","improve"],"description":"Marketing Signal funnel stage (Marketing Signal findings only)."},"title":{"type":"string"},"remediation":{"type":"string"},"affectedUrls":{"type":"array","items":{"type":"string"}}}}},"checks":{"type":"object","description":"Marketing check ledger summary (pass/fail/info/unverified) + rows.","required":["pass","fail","info","unverified","rows"],"properties":{"pass":{"type":"integer","minimum":0},"fail":{"type":"integer","minimum":0},"info":{"type":"integer","minimum":0},"unverified":{"type":"integer","minimum":0},"rows":{"type":"array","items":{"type":"object","description":"One structural probe row from the AI-readiness check ledger. info rows are emerging standards; unverified rows need rendered evidence. Neither is score-penalizing.","required":["id","label","category","status","detail"],"properties":{"id":{"type":"string","example":"mcp-server-card"},"label":{"type":"string","example":"MCP server card"},"category":{"type":"string","enum":["discoverability","structured_data","metadata","content_structure","accessibility","answerability","agent_operability","performance","security","general","findability","measurement","conversion_path","offer_clarity","trust_proof","schema_metadata","social_preview","performance_ux","consent_privacy_signal","connected_account"]},"status":{"type":"string","enum":["pass","fail","info","unverified"]},"detail":{"type":"string","example":"Not detected."}}}}}},"pagesCrawled":{"type":"integer","minimum":0},"scanMode":{"type":["string","null"],"example":"paid_marketing_signal"},"model":{"type":["string","null"]},"costUsd":{"type":"number","minimum":0},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"humanUrl":{"type":"string","description":"Human-readable Marketing dashboard view of this exact run."}}},{"type":"object","description":"Website Security report context (product=website_security). Includes the public-surface scope disclaimer, pillar rollup, deterministic check ledger, and bounded top findings.","required":["schemaVersion","product","runId","projectId","url","score","scoreLabel","execSummary","severityCounts","findingsTotal","topFindings","scope","pillars","checks","pagesScanned","scanMode","model","costUsd","createdAt","completedAt","humanUrl"],"properties":{"schemaVersion":{"type":"integer","example":2},"product":{"type":"string","enum":["website_security"]},"runId":{"type":"string","format":"uuid"},"projectId":{"type":["string","null"],"format":"uuid"},"url":{"type":"string","format":"uri"},"score":{"type":"integer","minimum":0,"maximum":100},"scoreStatus":{"type":"string","enum":["unverified"],"description":"Present when source-only evidence cannot support a numeric Website Security score."},"scoreLabel":{"type":"string","example":"Managed"},"execSummary":{"type":"string"},"severityCounts":{"type":"object","required":["critical","high","medium","low","info"],"properties":{"critical":{"type":"integer","minimum":0},"high":{"type":"integer","minimum":0},"medium":{"type":"integer","minimum":0},"low":{"type":"integer","minimum":0},"info":{"type":"integer","minimum":0}}},"findingsTotal":{"type":"integer","minimum":0},"topFindings":{"type":"array","maxItems":10,"items":{"type":"object","required":["findingId","severity","category","pillar","title","remediation","affectedUrls"],"properties":{"findingId":{"type":"string","example":"f_1a2b3c4d5e6f7a8b"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"category":{"type":"string","enum":["security"]},"pillar":{"type":"string","enum":["browser_defenses","transport_trust","dns_email_trust","cookies_sessions","exposure_reputation"]},"title":{"type":"string"},"remediation":{"type":"string"},"affectedUrls":{"type":"array","items":{"type":"string"}}}}},"scope":{"type":"object","required":["label","disclaimer","pagesScanned"],"properties":{"label":{"type":"string"},"disclaimer":{"type":"string"},"pagesScanned":{"type":"integer","minimum":0}}},"pillars":{"type":"array","items":{"type":"object","required":["key","label","score","weight","pass","fail"],"properties":{"key":{"type":"string","enum":["browser_defenses","transport_trust","dns_email_trust","cookies_sessions","exposure_reputation"]},"label":{"type":"string"},"score":{"type":["integer","null"],"minimum":0,"maximum":100,"description":"Null when the pillar has only unverified runtime-dependent checks."},"weight":{"type":"number","minimum":0,"maximum":100},"pass":{"type":"integer","minimum":0},"fail":{"type":"integer","minimum":0}}}},"checks":{"type":"array","items":{"type":"object","required":["id","label","pillar","status","severity","evidence","recommendation"],"properties":{"id":{"type":"string"},"label":{"type":"string"},"pillar":{"type":"string","enum":["browser_defenses","transport_trust","dns_email_trust","cookies_sessions","exposure_reputation"]},"status":{"type":"string","enum":["pass","fail","info","unverified"]},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"evidence":{"type":"string"},"recommendation":{"type":"string"}}}},"tls":{"type":"object","required":["valid"],"properties":{"valid":{"type":"boolean"},"issuer":{"type":"string"},"subject":{"type":"string"},"validTo":{"type":"string","format":"date-time"},"daysUntilExpiry":{"type":"number"},"error":{"type":"string"}}},"dns":{"type":"object","required":["hasMx","hasSpf","hasDmarc","hasCaa"],"properties":{"hasMx":{"type":"boolean"},"hasSpf":{"type":"boolean"},"hasDmarc":{"type":"boolean"},"hasCaa":{"type":"boolean"}}},"pagesScanned":{"type":"integer","minimum":0},"scanMode":{"type":["string","null"],"example":"paid_website_security"},"model":{"type":["string","null"]},"costUsd":{"type":"number","minimum":0},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"humanUrl":{"type":"string","description":"Human-readable Security dashboard view of this exact run."}}}]}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"409":{"description":"run_not_completed.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/webhooks":{"get":{"operationId":"list_webhooks","tags":["webhooks"],"summary":"List webhook endpoints","description":"Endpoints for this org. Signing secrets are never returned after creation.","responses":{"200":{"description":"Endpoint list."},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}},"post":{"operationId":"create_webhook","tags":["webhooks"],"summary":"Register a webhook endpoint","description":"Subscribe an https URL to events. The response includes the HMAC signing secret EXACTLY ONCE; verify x-index365-signature (t=<unix>,v1=<hmac-sha256 of '<t>.<body>'>) and reject timestamps older than 5 minutes. Events: run.completed, run.failed","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri","description":"https only."},"events":{"type":"array","items":{"type":"string","enum":["run.completed","run.failed"]}},"description":{"type":"string","maxLength":500}}},"example":{"url":"https://hooks.acme.com/index365","events":["run.completed","run.failed"]}}}},"responses":{"201":{"description":"Endpoint created; response carries the one-time secret."},"400":{"description":"invalid_json | validation_failed.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"409":{"description":"limit_reached: max endpoints for this org.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}},"/api/v1/webhooks/{webhookId}":{"get":{"operationId":"get_webhook","tags":["webhooks"],"summary":"Get one webhook endpoint","description":"Inspect one endpoint's url, events, and active state. The signing secret is never returned.","parameters":[{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Endpoint."},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}},"patch":{"operationId":"update_webhook","tags":["webhooks"],"summary":"Update a webhook endpoint","description":"Change url/events/description or toggle active.","parameters":[{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["run.completed","run.failed"]}},"description":{"type":["string","null"],"maxLength":500},"active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated endpoint."},"400":{"description":"invalid_json | validation_failed.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}},"delete":{"operationId":"delete_webhook","tags":["webhooks"],"summary":"Delete a webhook endpoint","description":"Permanently remove the endpoint and its delivery log. Prefer update_webhook with active=false to pause deliveries instead.","parameters":[{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"Missing/unknown/revoked API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"403":{"description":"Key lacks the required scope (error.code=insufficient_scope).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}},"429":{"description":"Rate limit exceeded (60 req/min per key). Honor Retry-After.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"additionalProperties":true}}}}}}}}}}}