{"openapi":"3.0.3","info":{"title":"SentientUI API","description":"Public management and ingest API for SentientUI — adaptive UI personalization platform. Rate limiting: every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset` (IETF draft) headers so clients can self-throttle; a `429` response additionally sets `Retry-After`. Deprecation policy: deprecated operations are marked `deprecated: true` in this spec and return `Deprecation` and `Sunset` (RFC 8594) response headers for at least 90 days before removal.","version":"1.0.0","contact":{"email":"support@sentient-ui.com"}},"components":{"securitySchemes":{"publicKey":{"type":"http","scheme":"bearer","description":"Public SDK key (pk_…) for ingest/assign endpoints. Sent as `Authorization: Bearer pk_…`."},"secretKey":{"type":"http","scheme":"bearer","description":"Secret key (sk_…) for management endpoints. Sent as `Authorization: Bearer sk_…`."},"editorToken":{"type":"http","scheme":"bearer","description":"Short-lived editor token issued to the on-site visual editor, scoped to one project. Sent as `Authorization: Bearer <token>`."}},"schemas":{"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable error code (snake_case)"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Correlates with server logs"},"retryAfter":{"type":"integer","description":"Seconds to wait before retrying (rate limits)"},"details":{"type":"object","additionalProperties":true,"description":"Error-specific metadata (e.g. plan, limit, feature, reason). Every 4xx carries error + message + requestId (lib/error-shape.ts); older top-level copies of these fields are kept for existing clients."},"issues":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Per-field validation problems, when applicable"}},"additionalProperties":true}}},"paths":{"/openapi.json":{"get":{"operationId":"getOpenapiJson","summary":"This OpenAPI document","tags":["infra"],"description":"The OpenAPI 3.0 description of this API, generated from the running server so it cannot drift from the routes it documents. Public, cacheable for an hour. A human-readable rendering of the same document is served at `/docs`. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"200":{"description":"An OpenAPI 3.0 document.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","description":"An OpenAPI 3.0 document.","additionalProperties":true}}}}}}},"/v1/health":{"get":{"operationId":"getHealth","summary":"Liveness probe","tags":["infra"],"description":"Liveness probe. Returns `{ \"ok\": true }` whenever the process is serving HTTP. It does not check Postgres, Redis, or any downstream dependency, so a `200` here means the process is up — not that every request will succeed. No authentication required. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","description":"Always `true` when the process is serving."}},"additionalProperties":false}}}}}}},"/healthz":{"get":{"operationId":"getHealthz","summary":"Liveness probe (legacy alias)","tags":["infra"],"description":"Liveness probe. Returns `{ \"ok\": true }` whenever the process is serving HTTP. It does not check Postgres, Redis, or any downstream dependency, so a `200` here means the process is up — not that every request will succeed. No authentication required. Legacy alias of `GET /v1/health`; prefer that path. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","description":"Always `true` when the process is serving."}},"additionalProperties":false}}}}}}},"/v1/health/worker":{"get":{"operationId":"getHealthWorker","summary":"Worker liveness probe","tags":["infra"],"description":"Reports whether the background worker is alive and its loop is progressing. `200` when healthy, `503` otherwise with `status` naming the failure: `process_dead` (the process stopped), `loop_wedged` (alive but not advancing), `never_seen` (no worker has ever reported). No authentication required. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["ok","status"],"properties":{"ok":{"type":"boolean"},"status":{"type":"string","description":"healthy | process_dead | loop_wedged | never_seen"},"seenAgoSeconds":{"type":"number","nullable":true},"tickAgoSeconds":{"type":"number","nullable":true}},"additionalProperties":false}}}},"503":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["ok","status"],"properties":{"ok":{"type":"boolean"},"status":{"type":"string","description":"healthy | process_dead | loop_wedged | never_seen"},"seenAgoSeconds":{"type":"number","nullable":true},"tickAgoSeconds":{"type":"number","nullable":true}},"additionalProperties":false}}}}}}},"/v1/events":{"post":{"operationId":"postEvents","summary":"Ingest an event batch","tags":["ingest"],"description":"Post a batch of SDK events (1–200). Events are deduplicated by `id`. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","minItems":1,"maxItems":200,"items":{"type":"object","required":["id","sessionId","projectId","componentId","eventType","timestamp","timeInSession"],"properties":{"id":{"type":"string","minLength":1,"maxLength":128,"description":"Client-generated unique event ID (UUID recommended)"},"sessionId":{"type":"string","minLength":1,"maxLength":128},"projectId":{"type":"string","description":"Your public API key — server overwrites with the authenticated project ID"},"componentId":{"type":"string","minLength":1,"maxLength":256},"variantId":{"type":"string","maxLength":128},"eventType":{"type":"string","enum":["variant_assigned","goal_achieved","scroll_depth","dwell","cursor_signal","component_visible","component_exited","micro_signal","funnel_declared","pageview","interaction_stats"]},"goalType":{"type":"string","maxLength":64},"path":{"type":"string","maxLength":2048,"description":"Page path the event occurred on, e.g. /pricing. Path only — query strings are not accepted."},"payload":{"type":"object","additionalProperties":true},"timestamp":{"type":"integer","minimum":0,"description":"Unix timestamp in milliseconds"},"timeInSession":{"type":"integer","minimum":0,"description":"Milliseconds since session start"}}}}}}},"security":[{"publicKey":[]}],"responses":{"202":{"description":"Batch accepted","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"integer","description":"Number of events actually stored. Lower than the batch size when events were already delivered — they deduplicate on `id`."},"rejected":{"type":"integer","description":"Events skipped because the sessionId belongs to a different project"}},"description":"Batch accepted"}}}},"400":{"description":"Validation error","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"issues":{"type":"array","items":{"type":"object"}}},"description":"Validation error"}}}},"401":{"description":"Missing or invalid API key","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"description":"Missing or invalid API key"}}}}}}},"/v1/sessions":{"post":{"operationId":"postSessions","summary":"Upsert a visitor session","tags":["ingest"],"description":"Create or update a session. Call once per page load before sending events. Returns 204 on success. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sessionId"],"properties":{"sessionId":{"type":"string","minLength":1,"maxLength":128,"description":"Stable UUID for this browser session"},"deviceClass":{"type":"string","maxLength":32,"nullable":true,"description":"mobile | tablet | desktop"},"trafficSource":{"type":"string","maxLength":64,"nullable":true,"description":"organic | paid | direct | referral | email | social"},"country":{"type":"string","minLength":2,"maxLength":2,"nullable":true,"description":"ISO 3166-1 alpha-2 country code"},"referrerDomain":{"type":"string","maxLength":256,"nullable":true},"utmParams":{"type":"object","additionalProperties":{"type":"string"},"description":"UTM parameters from the URL"},"clickIds":{"type":"object","additionalProperties":{"type":"string"},"description":"Ad-platform click IDs from the landing URL (gclid, gbraid, wbraid, fbclid, ttclid, msclkid, twclid, li_fat_id). Unknown keys are dropped, values capped at 256 chars. First value stored wins for the life of the session."},"timeOfDay":{"type":"string","maxLength":16,"nullable":true,"description":"morning | afternoon | evening | night"},"dayOfWeek":{"type":"string","maxLength":16,"nullable":true,"description":"monday … sunday"},"ephemeral":{"type":"boolean","default":false,"description":"If true, session and its data are purged after 24 h"},"userId":{"type":"string","minLength":1,"maxLength":256,"nullable":true,"description":"Your application user ID — links sessions across devices"},"automation":{"type":"boolean","default":false,"description":"Likely-automation hint (navigator.webdriver or agent UA). Excluded from bandit reward and shown separately in the dashboard."},"sdk":{"type":"string","maxLength":32,"nullable":true,"description":"Integration surface reporting in — 'snippet' | 'react' | 'core'. Set by the SDK itself; unknown names are ignored."},"sdkVersion":{"type":"string","maxLength":20,"nullable":true,"description":"The SDK's released build version (semver). Recorded so the dashboard can flag a project running an outdated SDK; ignored if it isn't semver-shaped."}}}}}},"security":[{"publicKey":[]}],"responses":{"204":{"description":"Session upserted","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}}},"400":{"description":"Validation error","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"issues":{"type":"array","items":{"type":"object"}}},"description":"Validation error"}}}},"401":{"description":"Missing or invalid API key","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"description":"Missing or invalid API key"}}}},"402":{"description":"Monthly session limit reached — the plan's allowance is pooled across the account's projects","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"plan":{"type":"string"},"limit":{"type":"integer"}},"description":"Monthly session limit reached — the plan's allowance is pooled across the account's projects"}}}},"409":{"description":"Session ID already owned by a different project","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"description":"Session ID already owned by a different project"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/assign":{"post":{"operationId":"postAssign","summary":"Assign a variant to a session","tags":["ingest"],"description":"Returns the variant to serve for a component — the one the bandit currently favours for the visitor's segment (it keeps exploring, so this is not a tested winner), or the promoted variant. Optionally stores agent-readable data alongside the assignment.\n\nA `404` response carries one of three `error` codes:\n- `unknown_session` — no session matches the given `sessionId` for this project.\n- `no_variants_configured` — the component has no assignable variants (e.g. cold start with no `variantIds`, or the free-plan component cap was reached); the SDK renders its default.\n- `holdout_baseline` — EXPECTED control-group outcome, not an error: the session is in the holdout and no baseline `variantIds` were declared, so the SDK keeps its default rendering. Treated as \"no assignment\" by the SDK. (A holdout session that DID declare `variantIds` gets a `200` with `holdout: true` and `variantId` = the declared baseline instead.). Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sessionId","componentId"],"properties":{"sessionId":{"type":"string","minLength":1,"maxLength":128},"componentId":{"type":"string","minLength":1,"maxLength":256},"variantIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":128},"minItems":1,"maxItems":20,"description":"Candidate variant IDs. Omit to use all configured variants."},"agentData":{"description":"Arbitrary data stored against the assigned variant and surfaced to AI agents"},"agentDataByVariant":{"type":"object","additionalProperties":true,"description":"Per-variant agent data — only the assigned variant's entry is stored"}}}}}},"security":[{"publicKey":[]}],"responses":{"200":{"description":"Variant assigned","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["variantId","assignmentTtlMs"],"properties":{"variantId":{"type":"string","description":"The assigned variant ID"},"assignmentTtlMs":{"type":"integer","description":"How long the client should cache this assignment (ms)"},"source":{"type":"string","enum":["promoted"],"description":"Present when an operator promoted this variant as the default (an operator decision, not a tested result)"},"content":{"description":"Managed content for this variant, if configured"},"holdout":{"type":"boolean","description":"Present (true) when the session is in the control group and received the declared baseline"}},"description":"Variant assigned"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/winner":{"get":{"operationId":"getWinner","summary":"Get the currently favoured variant for a component","tags":["ingest"],"description":"Returns the variant currently favoured by the optimizer (highest conversion rate among variants with at least 100 exposures) — NOT a tested winner. `evidence_state` says how strong the case is against the component's control (`evidence_control`); below the floor the baseline is returned with `basis: \"baseline_fallback\"`. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"publicKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"variantId":{"type":"string"},"basis":{"type":"string","enum":["currently_favoured","baseline_fallback","shadow_mode"],"description":"Why this variant: favoured by the evidence, or the baseline because none cleared the floor / the project is in shadow mode"},"evidence_state":{"type":"string","nullable":true,"description":"Evidence vs the component's control (not_enough_data | early_signal | moderate_evidence | strong_evidence | likely_worse | inconclusive); null when the favoured variant IS the control. Scope depends on `segment`. WITHOUT it: the arm's overall verdict — the same one GET /components prints for the arm (direct credit summed over segments, bars corrected over the component's non-control arms with trials). WITH `?segment=`: that segment's OWN verdict (this arm's cell vs the control's cell in the same segment, each needing the 100-exposure floor) — the value GET /components prints under the arm's `segments[]`, with bars corrected over every (non-control arm, segment) cell of the component that has trials, so a segment verdict is stricter than the overall one and the two can disagree."},"evidence_control":{"type":"string","nullable":true,"description":"The arm evidence_state is judged against (the component's evidence control, picked among variants with data — not necessarily variantIds[0])"},"min_sample":{"type":"integer","description":"Exposures a variant needs before it can be favoured"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/weights":{"get":{"operationId":"getWeights","summary":"Get the fallback ranking of variants per component","tags":["ingest"],"description":"Rank-only feed the SDK uses to pick a variant before `/v1/assign` resolves. Authenticated by a public key, so it deliberately carries NO real statistics: `rank` is 1 for the best arm, and `pulls`/`avgReward` are rank-encoded compatibility values (pulls is always 1, avgReward is monotone in rank), not traffic or conversion rates. Real per-variant stats are on the management API. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"publicKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"components":{"type":"array","items":{"type":"object","properties":{"componentId":{"type":"string"},"updatedAt":{"type":"number"},"variants":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string"},"rank":{"type":"number","description":"Dense rank, 1 = best fallback choice."},"pulls":{"type":"number","description":"Always 1 (compatibility field, not a count)."},"avgReward":{"type":"number","description":"Rank-encoded in (0, 1]; not a reward rate."}},"additionalProperties":true}}},"additionalProperties":true}}},"additionalProperties":true}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/agent/layout":{"get":{"operationId":"getAgentLayout","summary":"Get personalized layout for a visitor","tags":["agent"],"description":"Returns the currently favoured variant for every active component (highest observed conversion rate among variants with at least 30 exposures), resolved to the visitor's persona. This is NOT a tested winner: each block carries `evidence_state` against the component's control (100-exposure floor; only `strong_evidence` is a reliable result). The blocks and their evidence for one persona are computed at most once a minute per API machine, so they may be up to ~60s behind the data. Call from your backend or AI agent using an `sk_` key. Each call is logged as an agent event. Authenticate with a secret key (`Authorization: Bearer sk_…`). Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":128},"in":"query","name":"visitor_id","required":false,"description":"Session UUID from the visitor's browser cookie"},{"schema":{"type":"string","minLength":1,"maxLength":256},"in":"query","name":"user_id","required":false,"description":"Your application user ID — used when visitor_id is unavailable"}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Layout resolved","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["persona","confidence","blocks"],"properties":{"persona":{"type":"string","nullable":true,"description":"Visitor's cluster label, or null for anonymous visitors"},"confidence":{"type":"number","nullable":true,"description":"Portrait reliability score (0–1) when a persona is resolved, null otherwise — same metric as POST /v1/decide"},"blocks":{"type":"array","items":{"type":"object","required":["block","variant"],"properties":{"block":{"type":"string","description":"Component ID"},"variant":{"type":"string","description":"Currently favoured variant ID (not necessarily a proven winner — see evidence_state)"},"content":{"description":"Agent-readable data attached to this variant, if any"},"evidence_state":{"type":"string","nullable":true,"description":"Evidence the favoured variant beats the control: not_enough_data | early_signal | moderate_evidence | strong_evidence | likely_worse | inconclusive. Null when the favoured variant is the control itself."},"evidence_scope":{"type":"string","enum":["all_visitors"],"description":"Population the evidence was measured on (the favourite itself may be persona-specific)"}}}}},"description":"Layout resolved"}}}},"400":{"description":"Validation error","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"issues":{"type":"array","items":{"type":"object"}}},"description":"Validation error"}}}},"401":{"description":"Missing or invalid sk_ key","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"description":"Missing or invalid sk_ key"}}}},"429":{"description":"Rate limit exceeded","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"retryAfter":{"type":"number"}},"description":"Rate limit exceeded"}}}}}}},"/v1/crawler-events":{"post":{"operationId":"postCrawlerEvents","summary":"Log an AI crawler / agent HTTP read","tags":["ingest"],"description":"Record a UA-matched crawler or agent request against your site. Called server-side by the SDK's AdaptiveRoot server component and the createAgentFeed route — the only way to observe passive crawlers, which run no JavaScript. Feeds the dashboard \"% agentic visits\" figure. Never counted in impressions or CVR. The server re-derives the agent from `userAgent` (a request whose user agent matches no known agent is accepted and dropped), strips any query string from `path`, and collapses repeats of the same fetch within a 10-second bucket. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["path"],"properties":{"path":{"type":"string","minLength":1,"maxLength":2048,"description":"Request path that was read"},"botName":{"type":"string","maxLength":128,"nullable":true,"description":"Matched agent token (e.g. GPTBot)"},"userAgent":{"type":"string","maxLength":1024,"nullable":true},"source":{"type":"string","enum":["middleware","feed","ssr","edge","log_drain"],"default":"middleware"}}}}}},"security":[{"publicKey":[]}],"responses":{"204":{"description":"Logged","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/contact":{"post":{"operationId":"postContact","summary":"Send a message to the SentientUI team","tags":["public"],"description":"Public contact form endpoint. Rate-limited per IP; the recipient is fixed (the SentientUI team) and cannot be chosen by the caller. Backs the sentient-ui.com/contact form and its WebMCP tool. The `company` field is a honeypot — leave it empty. No authentication required. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","email","message"],"properties":{"name":{"type":"string","maxLength":200,"description":"Sender name."},"email":{"type":"string","maxLength":320,"description":"Sender email; used as the reply-to."},"message":{"type":"string","maxLength":5000,"description":"Message or question for the team."},"company":{"type":"string","description":"Honeypot — must be empty. Submissions with this set are silently discarded."}},"additionalProperties":true}}}},"security":[],"responses":{"200":{"description":"Message accepted (also returned for honeypot hits, so bots learn nothing).","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"description":"Message accepted (also returned for honeypot hits, so bots learn nothing)."}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/public/reports/{token}":{"get":{"operationId":"getPublicReportsByToken","summary":"Read a shared lift report","tags":["public"],"description":"The read-only lift report behind a shared link: personalized visitors vs. the held-back control group, with the always-valid interval, sample sizes, the time window and when it was computed. The token in the path is the credential; unknown, expired and revoked links all return 404. Rate-limited per IP; never cached by shared caches. No authentication required. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"token","required":true,"description":"The share token from the report link."}],"security":[],"responses":{"200":{"description":"Aggregate lift report. Contains no project id, key, or per-visitor data.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","description":"Aggregate lift report. Contains no project id, key, or per-visitor data.","properties":{"projectName":{"type":"string"},"goal":{"type":"object","properties":{"name":{"type":"string"},"scope":{"type":"string","enum":["primary","any"]}}},"evidence":{"type":"string","enum":["collecting","awaiting_conversions","not_significant","significant_positive","significant_negative"]},"liftPct":{"type":"number","nullable":true},"diffInterval":{"type":"object","properties":{"lower":{"type":"number"},"upper":{"type":"number"}},"nullable":true},"alpha":{"type":"number"},"rates":{"type":"object","properties":{"personalized":{"type":"number"},"control":{"type":"number"}},"nullable":true},"samples":{"type":"object","properties":{"personalized":{"type":"object","properties":{"visitors":{"type":"number"},"conversions":{"type":"number"}}},"control":{"type":"object","properties":{"visitors":{"type":"number"},"conversions":{"type":"number"}}},"minPerArm":{"type":"number"}}},"epochs":{"type":"number"},"controlShare":{"type":"number"},"splitCheck":{"type":"object","properties":{"state":{"type":"string"},"summary":{"type":"string"},"windowDays":{"type":"number"}},"nullable":true},"window":{"type":"object","properties":{"from":{"type":"string","nullable":true},"to":{"type":"string"}}},"computedAt":{"type":"string"},"shadowMode":{"type":"boolean"},"expiresAt":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/apply":{"post":{"operationId":"postApply","summary":"Apply to the SentientUI design cohort","tags":["public"],"description":"Public application form for the design cohort. Rate-limited per IP; the recipients are fixed (the cohort owners) and cannot be chosen by the caller. Backs the sentient-ui.com/apply form. The `phone` field is a honeypot — leave it empty. No authentication required. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","email","company","targetPage","monthlySessions","stack","goal","devResource","founderAttends","publishingConsent","feeAcknowledged"],"properties":{"name":{"type":"string","maxLength":200,"description":"Applicant name."},"email":{"type":"string","maxLength":320,"description":"Applicant email; used as the reply-to."},"company":{"type":"string","maxLength":200,"description":"Company name."},"targetPage":{"type":"string","maxLength":500,"description":"URL of the target page (pricing, signup, or onboarding)."},"monthlySessions":{"type":"string","enum":["under_10k","10k_50k","50k_250k","250k_plus"],"description":"Monthly sessions on the target page."},"stack":{"type":"string","enum":["nextjs","react","nocode","wordpress","other"],"description":"What the target page is built with. Any stack is eligible."},"goal":{"type":"string","maxLength":1000,"description":"The one number to move, and where it is today."},"devResource":{"type":"string","maxLength":500,"description":"Who can install the SDK within week 1 of kickoff."},"distribution":{"type":"string","maxLength":1000,"description":"Optional: audience, newsletter, podcast, or network."},"founderAttends":{"type":"boolean","description":"The founder (or owner of the conversion number) attends kickoff and readout."},"publishingConsent":{"type":"boolean","description":"Agrees to a real holdout and results published with their name, win or lose."},"feeAcknowledged":{"type":"boolean","description":"Acknowledges the $499 fee, paid before kickoff and credited toward a plan."},"phone":{"type":"string","description":"Honeypot — must be empty. Submissions with this set are silently discarded."}},"additionalProperties":true}}}},"security":[],"responses":{"200":{"description":"Application accepted (also returned for honeypot hits, so bots learn nothing).","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"description":"Application accepted (also returned for honeypot hits, so bots learn nothing)."}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/scan":{"post":{"operationId":"postScan","summary":"Run a first-impression scan of a public website","tags":["public"],"description":"Fetches the homepage plus robots.txt/llms.txt of a public https site and scores what visitors and AI agents can see in the server HTML. Rate-limited per IP and globally; results for a host are cached for 24 hours. Returns a scan id for the report page. No authentication required. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","maxLength":2048,"description":"Site URL or bare domain (https assumed)."}}}}}},"security":[],"responses":{"200":{"description":"Scan stored (or served from the 24h per-host cache).","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"cached":{"type":"boolean"}},"description":"Scan stored (or served from the 24h per-host cache)."}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/scan/{id}":{"get":{"operationId":"getScanById","summary":"Teaser view of a first-impression scan","tags":["public"],"description":"Score and headline findings only. The full report requires a signed-in read via the management API. No authentication required. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Scan id."}],"responses":{"200":{"description":"Teaser: score, top findings, and locked counts.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"host":{"type":"string"},"url":{"type":"string"},"score":{"type":"number"},"headline":{"type":"array","items":{"type":"string"}},"locked":{"type":"object","properties":{"findings":{"type":"number"},"targets":{"type":"number"}}},"createdAt":{"type":"string"}},"description":"Teaser: score, top findings, and locked counts."}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/qualify":{"post":{"operationId":"postQualify","summary":"Estimate whether a site has enough traffic to prove a result","tags":["public"],"description":"Sizes a held-back-control test against the visitor's traffic and conversion rate. Returns a coarse horizon and the monthly traffic that would reach a verdict quickly. Stateless and unauthenticated — nothing is stored. No authentication required. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["monthlySessions"],"properties":{"monthlySessions":{"type":"number","description":"Visitors per month to the page you would test."},"contextType":{"type":"string","description":"saas | ecommerce | marketing | landing | internal | marketplace"},"conversionRatePct":{"type":"number","description":"Your own conversion rate as a percentage, if you know it."}}}}}},"security":[],"responses":{"200":{"description":"Coarse feasibility verdict.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"verdict":{"type":"string","description":"fast | workable | too_slow | not_estimable"},"horizon":{"type":"string","nullable":true},"sessionsNeededPerMonth":{"type":"number","nullable":true},"headline":{"type":"string"},"detail":{"type":"string"},"basis":{"type":"object","additionalProperties":true},"methodNote":{"type":"string"}},"additionalProperties":true,"description":"Coarse feasibility verdict."}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mcp/demo":{"post":{"operationId":"postMcpDemo","summary":"Provision an anonymous MCP demo token","tags":["ingest"],"description":"Provision an anonymous MCP demo token. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"publicKey":[]}],"responses":{"200":{"description":"Demo token provisioned","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Anonymous demo bearer token (demo_ prefix)"},"projectId":{"type":"string","description":"UUID of the provisioned demo project"},"callsRemaining":{"type":"integer","description":"MCP calls left on this demo token"}},"additionalProperties":true,"description":"Demo token provisioned"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"operationId":"getWellKnownOauthProtectedResource","summary":"OAuth 2.0 protected resource metadata (RFC 9728)","tags":["infra"],"description":"Tells an MCP client which authorization server issues tokens for this resource, which bearer methods are supported, and which scopes to request. Clients reach it from the `WWW-Authenticate` challenge on a `401` from `/mcp`. Public. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/.well-known/oauth-protected-resource/mcp":{"get":{"operationId":"getWellKnownOauthProtectedResourceMcp","summary":"OAuth 2.0 protected resource metadata, resource-suffixed path","tags":["infra"],"description":"Tells an MCP client which authorization server issues tokens for this resource, which bearer methods are supported, and which scopes to request. Clients reach it from the `WWW-Authenticate` challenge on a `401` from `/mcp`. Public. Same document as `/.well-known/oauth-protected-resource`, at the path some clients build from the resource URL. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"operationId":"getWellKnownOauthAuthorizationServer","summary":"Redirect to the authorization server metadata","tags":["infra"],"description":"The real document lives at the issuer (Clerk). Responds `302` to the issuer's `/.well-known/oauth-authorization-server`, or `404` when no issuer is configured. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"404":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/.well-known/openid-configuration":{"get":{"operationId":"getWellKnownOpenidConfiguration","summary":"Redirect to the OpenID Connect discovery document","tags":["infra"],"description":"Answers agents and crawlers that probe the conventional OIDC path on this origin. Responds `302` to the issuer's `/.well-known/openid-configuration` — a redirect rather than a proxy, so the `issuer` in the body always matches the host the client lands on. `404` when no issuer is configured. Real MCP clients should use the RFC 9728 flow above. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"404":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/mcp":{"post":{"operationId":"postMcp","summary":"MCP JSON-RPC endpoint (Streamable HTTP)","tags":["infra"],"description":"MCP Streamable HTTP transport. Send a JSON-RPC 2.0 request (or batch) and receive either a JSON response or an SSE stream, depending on the negotiated `Accept`. The server is stateless: no session is created, so no `Mcp-Session-Id` is required.\n\nDiscovery is public — `initialize`, `ping`, `tools/list`, `prompts/list`, `resources/list`, `resources/templates/list`, and `resources/read` of a static `ui://sentientui/*` template all answer without a bearer token, so registries and readiness crawlers can enumerate the server. Everything else, `tools/call` included, requires `Authorization: Bearer <sk_… or OAuth token>` and answers `401` with an RFC 9728 `WWW-Authenticate: Bearer resource_metadata=\"…\"` challenge. A batch mixing a public method with an authenticated one is treated as authenticated. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}},"get":{"operationId":"getMcp","summary":"Not allowed — /mcp accepts POST only","tags":["infra"],"description":"The transport runs in stateless mode: there is no server-initiated SSE stream to GET and no session to DELETE. Always `405` with `Allow: POST`. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"405":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"jsonrpc":{"type":"string","description":"Always `\"2.0\"`."},"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"integer","description":"JSON-RPC error code."},"message":{"type":"string"}}},"id":{"description":"Echoes the request id, or null when it could not be read."}},"additionalProperties":true}}}}}},"delete":{"operationId":"deleteMcp","summary":"Not allowed — /mcp accepts POST only","tags":["infra"],"description":"The transport runs in stateless mode: there is no server-initiated SSE stream to GET and no session to DELETE. Always `405` with `Allow: POST`. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"405":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"jsonrpc":{"type":"string","description":"Always `\"2.0\"`."},"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"integer","description":"JSON-RPC error code."},"message":{"type":"string"}}},"id":{"description":"Echoes the request id, or null when it could not be read."}},"additionalProperties":true}}}}}}},"/.well-known/mcp":{"post":{"operationId":"postWellKnownMcp","summary":"MCP JSON-RPC endpoint at the well-known discovery path","tags":["infra"],"description":"MCP Streamable HTTP transport. Send a JSON-RPC 2.0 request (or batch) and receive either a JSON response or an SSE stream, depending on the negotiated `Accept`. The server is stateless: no session is created, so no `Mcp-Session-Id` is required.\n\nDiscovery is public — `initialize`, `ping`, `tools/list`, `prompts/list`, `resources/list`, `resources/templates/list`, and `resources/read` of a static `ui://sentientui/*` template all answer without a bearer token, so registries and readiness crawlers can enumerate the server. Everything else, `tools/call` included, requires `Authorization: Bearer <sk_… or OAuth token>` and answers `401` with an RFC 9728 `WWW-Authenticate: Bearer resource_metadata=\"…\"` challenge. A batch mixing a public method with an authenticated one is treated as authenticated.\n\nIdentical to `POST /mcp` — same handler, same auth rules — served here so a crawler probing the conventional discovery path gets a live handshake rather than a static manifest. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}},"get":{"operationId":"getWellKnownMcp","summary":"Not allowed — /.well-known/mcp accepts POST only","tags":["infra"],"description":"The transport runs in stateless mode: there is no server-initiated SSE stream to GET and no session to DELETE. Always `405` with `Allow: POST`. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"405":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"jsonrpc":{"type":"string","description":"Always `\"2.0\"`."},"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"integer","description":"JSON-RPC error code."},"message":{"type":"string"}}},"id":{"description":"Echoes the request id, or null when it could not be read."}},"additionalProperties":true}}}}}},"delete":{"operationId":"deleteWellKnownMcp","summary":"Not allowed — /.well-known/mcp accepts POST only","tags":["infra"],"description":"The transport runs in stateless mode: there is no server-initiated SSE stream to GET and no session to DELETE. Always `405` with `Allow: POST`. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"405":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"jsonrpc":{"type":"string","description":"Always `\"2.0\"`."},"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"integer","description":"JSON-RPC error code."},"message":{"type":"string"}}},"id":{"description":"Echoes the request id, or null when it could not be read."}},"additionalProperties":true}}}}}}},"/v1/graph/sync":{"post":{"operationId":"postGraphSync","summary":"Sync the component graph for a page","tags":["ingest"],"description":"Sync the component graph for a page. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["pageUrl","nodes","edges"],"description":"Full component graph (nodes + edges) for one page. Edges for the page are replaced.","properties":{"pageUrl":{"type":"string","description":"Absolute URL of the page whose graph is being synced."},"nodes":{"type":"array","maxItems":500,"items":{"type":"object","required":["componentId","contentHash"],"properties":{"componentId":{"type":"string","description":"Stable component identifier (1–256 chars)."},"semanticType":{"type":"string","enum":["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"],"description":"Semantic role of the component."},"answers":{"type":"array","items":{"type":"string"},"description":"Questions/answers this component addresses. Defaults to []."},"contentHash":{"type":"string","description":"Content fingerprint used to detect changes (≤128 chars)."},"prominenceScore":{"type":"number","description":"Visual prominence in [0, 1]. Defaults to 0.5."},"depthInPage":{"type":"integer","description":"Zero-based vertical position in the page. Defaults to 0."},"locator":{"type":"object","description":"Compound locator for this section. The server hashes it into a stable section_key — the same identity the crawler derives for the same section. Omit when nothing resolves uniquely.","additionalProperties":true}},"additionalProperties":true},"description":"Components on the page (max 500)."},"edges":{"type":"array","maxItems":2000,"items":{"type":"object","required":["fromComponentId","toComponentId","type"],"properties":{"fromComponentId":{"type":"string","description":"Source component id (1–256 chars)."},"toComponentId":{"type":"string","description":"Target component id (1–256 chars)."},"type":{"type":"string","enum":["structural","semantic","relevance"],"description":"Relationship type between the two components."},"weight":{"type":"number","description":"Edge weight in [0, 1]. Defaults to 1."},"confidence":{"type":"number","description":"Confidence in [0, 1]. Defaults to 0.5."}},"additionalProperties":true},"description":"Relationships between components (max 2000)."}},"additionalProperties":true}}},"description":"Full component graph (nodes + edges) for one page. Edges for the page are replaced."},"security":[{"publicKey":[]}],"responses":{"204":{"description":"Graph synced","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/visitors/erase":{"post":{"operationId":"postMgmtProjectsByIdVisitorsErase","summary":"Erase every session of one of your users (right-to-erasure by user id)","tags":["mgmt"],"description":"For a data-subject request where you know the customer's user id (the `userId` you pass to `identify()` / `POST /v1/sessions`) rather than a browser cookie. Every session carrying that user id stops being served and recorded immediately, and its stored data (events, portraits, decisions, goal events, attributions) is deleted — up to 200 sessions in this call, any beyond that within the hour by the background erasure pass (`sessionsPending`). Agent-layout log rows for the user id are deleted too. Requires editor or admin access to the project. Irreversible. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["userId"],"properties":{"userId":{"type":"string","description":"Your application user id (1–256 chars), as sent to identify()."}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"sessionsFound":{"type":"integer","description":"Sessions carrying this user id — all are no longer served or recorded."},"sessionsErased":{"type":"integer","description":"Sessions whose data was deleted in this call."},"sessionsPending":{"type":"integer","description":"Sessions left for the background erasure pass (within the hour)."},"agentEventsErased":{"type":"integer","description":"Agent-layout log rows for this user id, deleted."}},"required":["sessionsFound","sessionsErased","sessionsPending","agentEventsErased"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/visitor":{"delete":{"operationId":"deleteVisitor","summary":"Erase all data for a visitor (GDPR right-to-erasure)","tags":["ingest"],"description":"Marks the visitor session for erasure: personalization and data collection stop immediately, and all stored data is hard-deleted after a short grace window with no further action required. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sessionId"],"description":"Identifies the visitor session to erase.","properties":{"sessionId":{"type":"string","description":"The visitor session id (_snt_uid) whose data should be erased."}},"additionalProperties":true}}},"description":"Identifies the visitor session to erase."},"security":[{"publicKey":[]}],"responses":{"204":{"description":"Visitor erasure scheduled; the visitor is no longer served or recorded","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/decide":{"post":{"operationId":"postDecide","summary":"Decide layout order, variant assignments, and slot arms for a session","tags":["ingest"],"description":"Decide layout order, variant assignments, and slot arms for a session. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sessionId"],"description":"Decision request. At least one of `sections`, `components`, or `slots` must be non-empty (or use `slotsFrom: registry`).","properties":{"sessionId":{"type":"string","description":"Stable per-device visitor/session id (the _snt_uid cookie)."},"sections":{"type":"array","description":"Page sections eligible for layout reordering.","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"Section/component id."}},"additionalProperties":true}},"components":{"type":"array","description":"Components to assign a variant for.","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"Component id."},"variantIds":{"type":"array","items":{"type":"string"},"description":"Candidate variant ids to choose among (1–20)."}},"additionalProperties":true}},"slots":{"type":"array","description":"Declared slots to decide arms for (max 30).","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"Slot id."},"arms":{"type":"array","items":{"type":"string"},"description":"Candidate arm labels (2–12). Provide `arms` OR `dims`, not both."},"dims":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"description":"Named dimensions, each with 2–6 values (1–4 dims; value product ≤ 64). Provide `dims` OR `arms`."},"baseline":{"description":"Declared baseline: an arm string, or a per-dimension { dim: value } map."}},"additionalProperties":true}},"slotsFrom":{"type":"string","enum":["request","registry"],"description":"Slot source. 'registry' serves the project's PUBLISHED slot_definitions as if declared here. Defaults to 'request'."},"registrySlotIds":{"type":"array","items":{"type":"string"},"description":"Registry mode only: decide just these published slot ids (0–50) — the components actually on the page. An empty list decides none."},"bootstrap":{"type":"boolean","enum":[false],"description":"Registry mode only: false omits editor goals and sectionMap (snippet bootstrap data)."},"v":{"type":"string","description":"Snippet build version (semver, e.g. \"0.5.2\"), sent for version-skew reporting."},"pp":{"type":"integer","description":"Snippet inline pre-paint script contract version, or 0 when the install has no inline script. Install-health reporting only; no serving behaviour depends on it."}},"additionalProperties":true}}},"description":"Decision request. At least one of `sections`, `components`, or `slots` must be non-empty (or use `slotsFrom: registry`)."},"security":[{"publicKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"layoutOrder":{"type":"array","items":{"type":"string"}},"assignments":{"type":"object","additionalProperties":true},"persona":{"type":"string"},"confidence":{"type":"number"},"holdout":{"type":"boolean"},"slots":{"type":"object","additionalProperties":true},"slotConfig":{"type":"object","additionalProperties":true},"goals":{"type":"array","items":{"type":"object","additionalProperties":true}},"palette":{"type":"object","additionalProperties":true,"description":"Derived site palette for Composition Block rendering (registry decisions carrying blocks only)."},"vocabulary":{"type":"object","additionalProperties":true,"description":"The site-style entries the served Redesign (compose) arms borrow."}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/slots/observed":{"post":{"operationId":"postSlotsObserved","summary":"Report mounted AdaptiveSlot ids so they appear as draft slots","tags":["ingest"],"description":"Report mounted AdaptiveSlot ids so they appear as draft slots. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["slotIds"],"properties":{"slotIds":{"type":"array","items":{"type":"string"},"description":"Slot ids mounted in the app that received no server config (max 20 per call)."},"baselineSkeletons":{"type":"object","additionalProperties":true,"description":"Optional slot id → region skeleton (or {status}). Stored only while the slot has none."},"baselineTexts":{"type":"object","additionalProperties":{"type":"string"},"description":"Optional slot id → rendered baseline text (≤400 chars kept). Stored once reporters from several distinct networks, each on a scored-human session with events, agree on the same text; never overwritten after, and never over an owner-set text."},"sessionId":{"type":"string","description":"The reporting page session. A baseline-text vote only counts toward storage once this session is scored human and has events."}},"additionalProperties":true}}}},"security":[{"publicKey":[]}],"responses":{"202":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/registry/locators":{"get":{"operationId":"getRegistryLocators","summary":"List published component locators for page-scoped decides","tags":["ingest"],"description":"List published component locators for page-scoped decides. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"publicKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"slots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["tokens","arms"]},"locator":{"type":"object","additionalProperties":true,"nullable":true}},"additionalProperties":true}}},"additionalProperties":true}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/exchange":{"post":{"operationId":"postEditorExchange","summary":"Exchange a one-time editor code for an editor token","tags":["editor"],"description":"The dashboard opens the site with `#sentient_editor_code=<code>` (a 60 s, single-use code in the URL fragment, never a query parameter). The on-site editor posts it here from the site itself; the Origin must be on the project's allowed origins. Returns the short-lived editor token, which the editor keeps in memory/sessionStorage only. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string"}},"additionalProperties":false}}}},"security":[{"editorToken":[]}],"responses":{"200":{"description":"Editor token issued; the code is spent","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"expiresInMs":{"type":"integer"}},"additionalProperties":true,"description":"Editor token issued; the code is spent"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/verify":{"get":{"operationId":"getEditorVerify","summary":"Verify an editor token","tags":["editor"],"description":"Verify an editor token. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"editorToken":[]}],"responses":{"200":{"description":"Token is valid; projectId it grants draft access to","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"projectId":{"type":"string"}},"additionalProperties":true,"description":"Token is valid; projectId it grants draft access to"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/slots":{"get":{"operationId":"getEditorSlots","summary":"List draft/published slot definitions","tags":["editor"],"description":"List draft/published slot definitions. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"editorToken":[]}],"responses":{"200":{"description":"Slot definitions for the token project","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"slots":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true,"description":"Slot definitions for the token project"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/cell-preview":{"get":{"operationId":"getEditorCellPreview","summary":"The arm an on-site preview should render for one (slot, visitor type) square","tags":["editor"],"description":"The arm an on-site preview should render for one (slot, visitor type) square. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"slotId","required":true,"description":"Slot whose square to preview."},{"schema":{"type":"string"},"in":"query","name":"persona","required":true,"description":"Visitor-type key of the square."}],"security":[{"editorToken":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/targets":{"get":{"operationId":"getEditorTargets","summary":"List audit-detected targets","tags":["editor"],"description":"List audit-detected targets. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"editorToken":[]}],"responses":{"200":{"description":"Detected elements for overlay pre-highlighting","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"targets":{"type":"array","items":{"type":"object","additionalProperties":true}},"fonts":{"type":"array","items":{"type":"string"},"description":"Font families the site already loads"}},"additionalProperties":true,"description":"Detected elements for overlay pre-highlighting"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/region-skeleton":{"post":{"operationId":"postEditorRegionSkeleton","summary":"Replace a region skeleton from the on-site editor","tags":["editor"],"description":"Replace a region skeleton from the on-site editor. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["slotId"],"description":"The trusted refresh: the operator says the page changed. Overwrites whatever /v1 stored and resumes any drift suspension.","properties":{"slotId":{"type":"string","description":"Slot whose region was re-captured."},"skeleton":{"type":"object","additionalProperties":true,"description":"The captured skeleton."},"status":{"type":"string","enum":["too_large","empty","unaddressable"],"description":"Why no skeleton could be captured."}},"additionalProperties":true}}},"description":"The trusted refresh: the operator says the page changed. Overwrites whatever /v1 stored and resumes any drift suspension."},"security":[{"editorToken":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/slots/{slotId}":{"post":{"operationId":"postEditorSlotsBySlotId","summary":"Upsert a draft slot","tags":["editor"],"description":"Upsert a draft slot. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["kind","draftConfig"],"description":"Draft slot definition. Always written as a draft; never publishes.","properties":{"kind":{"type":"string","enum":["tokens","arms"],"description":"Slot type — 'tokens' (design-token variants) or 'arms' (discrete arms)."},"target":{"type":"object","description":"Optional DOM/target descriptor identifying where the slot renders.","additionalProperties":true},"draftConfig":{"type":"object","description":"Draft configuration for the slot, validated per `kind`.","additionalProperties":true}},"additionalProperties":true}}},"description":"Draft slot definition. Always written as a draft; never publishes."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier to upsert (1–128 chars)."}],"security":[{"editorToken":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteEditorSlotsBySlotId","summary":"Discard a draft slot from the on-site editor","tags":["editor"],"description":"Discard a draft slot from the on-site editor. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier to discard (1–128 chars)."}],"security":[{"editorToken":[]}],"responses":{"200":{"description":"Draft deleted; nothing was ever live","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true,"description":"Draft deleted; nothing was ever live"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/slots/{slotId}/publish":{"post":{"operationId":"postEditorSlotsBySlotIdPublish","summary":"Publish a draft slot from the on-site editor","tags":["editor"],"description":"Publish a draft slot from the on-site editor. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier to publish (1–128 chars)."}],"security":[{"editorToken":[]}],"responses":{"200":{"description":"Draft promoted to published; live for new visitors","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"publishedVersion":{"type":"number"}},"additionalProperties":true,"description":"Draft promoted to published; live for new visitors"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/goals/{goalId}":{"post":{"operationId":"postEditorGoalsByGoalId","summary":"Upsert a draft goal","tags":["editor"],"description":"Upsert a draft goal. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event"],"description":"Draft goal definition. Written as a draft; an already-live goal is left untouched (409).","properties":{"event":{"type":"string","enum":["click","form_submit","url_reached","scroll_depth"],"description":"Conversion event type that fulfils the goal."},"threshold":{"type":"number","nullable":true,"description":"For scroll_depth goals: how far down the page counts, in (0, 1]."},"locator":{"type":"object","description":"Optional element locator for click/form_submit goals.","additionalProperties":true},"urlPattern":{"type":"string","nullable":true,"description":"URL pattern for url_reached goals (1–512 chars)."},"slotId":{"type":"string","nullable":true,"description":"Optional slot this goal is associated with (1–128 chars)."},"displayName":{"type":"string","nullable":true,"description":"Human-readable name shown in the dashboard (1–120 chars). Derived from the locator/url when omitted."}},"additionalProperties":true}}},"description":"Draft goal definition. Written as a draft; an already-live goal is left untouched (409)."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"goalId","required":true,"description":"Goal identifier to upsert (1–128 chars)."}],"security":[{"editorToken":[]}],"responses":{"200":{"description":"Draft goal written","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"status":{"type":"string"}},"additionalProperties":true,"description":"Draft goal written"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteEditorGoalsByGoalId","summary":"Discard a draft goal from the on-site editor","tags":["editor"],"description":"Discard a draft goal from the on-site editor. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"goalId","required":true,"description":"Goal identifier to discard (1–128 chars)."}],"security":[{"editorToken":[]}],"responses":{"200":{"description":"Draft deleted; it was never tracking","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true,"description":"Draft deleted; it was never tracking"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/goals/{goalId}/publish":{"post":{"operationId":"postEditorGoalsByGoalIdPublish","summary":"Activate a draft goal from the on-site editor","tags":["editor"],"description":"Activate a draft goal from the on-site editor. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"goalId","required":true,"description":"Goal identifier to activate (1–128 chars)."}],"security":[{"editorToken":[]}],"responses":{"200":{"description":"Draft goal activated; tracking starts with the next visitor","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"status":{"type":"string"}},"additionalProperties":true,"description":"Draft goal activated; tracking starts with the next visitor"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/goals":{"get":{"operationId":"getEditorGoals","summary":"List goal definitions (editor scope)","tags":["editor"],"description":"List goal definitions (editor scope). Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"editorToken":[]}],"responses":{"200":{"description":"Goal definitions (active + draft)","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"goals":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true,"description":"Goal definitions (active + draft)"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/funnels":{"get":{"operationId":"getEditorFunnels","summary":"List funnels (editor scope)","tags":["editor"],"description":"List funnels (editor scope). Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"editorToken":[]}],"responses":{"200":{"description":"Funnel definitions with ordered steps","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"funnels":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true,"description":"Funnel definitions with ordered steps"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/funnels/{funnelId}":{"post":{"operationId":"postEditorFunnelsByFunnelId","summary":"Save a draft funnel","tags":["editor"],"description":"Save a draft funnel. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["steps"],"description":"Draft funnel definition. An already-live funnel is left untouched (409).","properties":{"displayName":{"type":"string","nullable":true,"description":"Human-readable funnel name."},"steps":{"type":"array","description":"Ordered steps (2–12), each an existing goal id.","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}},"description":"Draft funnel definition. An already-live funnel is left untouched (409)."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"funnelId","required":true,"description":"Funnel slug (lowercase, 1–128 chars)."}],"security":[{"editorToken":[]}],"responses":{"200":{"description":"Draft funnel written","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"status":{"type":"string"}},"additionalProperties":true,"description":"Draft funnel written"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/funnels/{funnelId}/publish":{"post":{"operationId":"postEditorFunnelsByFunnelIdPublish","summary":"Publish a draft funnel","tags":["editor"],"description":"Publish a draft funnel. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"funnelId","required":true,"description":"Funnel slug to activate."}],"security":[{"editorToken":[]}],"responses":{"200":{"description":"Funnel activated","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"status":{"type":"string"}},"additionalProperties":true,"description":"Funnel activated"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/funnels/{funnelId}/assign":{"post":{"operationId":"postEditorFunnelsByFunnelIdAssign","summary":"Assign a slot to a funnel step","tags":["editor"],"description":"Assign a slot to a funnel step. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["slotId"],"description":"Attach the slot to the funnel (optionally at a specific step).","properties":{"slotId":{"type":"string","description":"Slot to attach (1–128 chars)."},"stepIndex":{"type":"integer","nullable":true,"description":"0-based step the slot serves, when known."}},"additionalProperties":true}}},"description":"Attach the slot to the funnel (optionally at a specific step)."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"funnelId","required":true,"description":"Funnel the slot serves."}],"security":[{"editorToken":[]}],"responses":{"200":{"description":"Membership recorded","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true,"description":"Membership recorded"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/style-vocabulary":{"post":{"operationId":"postEditorStyleVocabulary","summary":"Store the site style vocabulary sampled from the live page","tags":["editor"],"description":"Store the site style vocabulary sampled from the live page. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Class lists the site uses for its buttons, headings, text, cards and sections, with computed colors, plus site images. Each entry is validated on its own; a bad one is dropped.","properties":{"entries":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Sampled style entries."},"images":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Site images with alt text."}},"additionalProperties":true}}},"description":"Class lists the site uses for its buttons, headings, text, cards and sections, with computed colors, plus site images. Each entry is validated on its own; a bad one is dropped."},"security":[{"editorToken":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/palette":{"post":{"operationId":"postEditorPalette","summary":"Store the derived site palette","tags":["editor"],"description":"Store the derived site palette. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["primaryBg","primaryText","radius"],"description":"Palette sampled from the live page (computed styles): dominant button background/text color and corner radius. Plain colors and px only.","properties":{"primaryBg":{"type":"string","description":"Primary button background (hex or rgb/rgba)."},"primaryText":{"type":"string","description":"Primary button text color (hex or rgb/rgba)."},"radius":{"type":"string","description":"Button corner radius, e.g. \"8px\" (≤ 100px)."}},"additionalProperties":true}}},"description":"Palette sampled from the live page (computed styles): dominant button background/text color and corner radius. Plain colors and px only."},"security":[{"editorToken":[]}],"responses":{"200":{"description":"Palette stored","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true,"description":"Palette stored"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/arrangements":{"get":{"operationId":"getEditorArrangements","summary":"List the composition arrangement catalog (editor scope)","tags":["editor"],"description":"List the composition arrangement catalog (editor scope). Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"editorToken":[]}],"responses":{"200":{"description":"Arrangement names, descriptions and fields.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"arrangements":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true,"description":"Arrangement names, descriptions and fields."}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/arrangements/{arrangementId}/instantiate":{"post":{"operationId":"postEditorArrangementsByArrangementIdInstantiate","summary":"Instantiate an arrangement (editor scope)","tags":["editor"],"description":"Instantiate an arrangement (editor scope). Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"fieldId → value; text fields fall back to defaults, link fields are required.","properties":{"fields":{"type":"object","additionalProperties":{"type":"string"}}},"additionalProperties":true}}},"description":"fieldId → value; text fields fall back to defaults, link fields are required."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"arrangementId","required":true,"description":"Arrangement id."}],"security":[{"editorToken":[]}],"responses":{"200":{"description":"The instantiated, validated block tree.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"blocks":{"type":"object","additionalProperties":true}},"additionalProperties":true,"description":"The instantiated, validated block tree."}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/suggest":{"post":{"operationId":"postEditorSuggest","summary":"AI test suggestions for the selected element","tags":["editor"],"description":"AI test suggestions for the selected element. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["element","pageUrl"],"description":"Selected-element context (tag, visible text, section type), an optional plain-English instruction, and the sampled palette. Returns up to 3 conservative, total-validated suggestions — every one lands in a prefilled form the operator confirms; nothing auto-applies.","properties":{"element":{"type":"object"},"pageUrl":{"type":"string"},"instruction":{"type":"string","description":"What the operator asked for, in their own words. Omit for unprompted ideas."},"palette":{"type":"object"}},"additionalProperties":false}}},"description":"Selected-element context (tag, visible text, section type), an optional plain-English instruction, and the sampled palette. Returns up to 3 conservative, total-validated suggestions — every one lands in a prefilled form the operator confirms; nothing auto-applies."},"security":[{"editorToken":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"suggestions":{"type":"array"},"locked":{"type":"boolean","description":"True when the plan does not include AI suggestions"},"exhausted":{"type":"boolean","description":"True when today’s shared AI budget (chat + copy wizard + suggestions) is spent"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/editor/chat":{"post":{"operationId":"postEditorChat","summary":"On-site editor AI chat (streaming, creates drafts)","tags":["editor"],"description":"Streams one assistant turn as `text/event-stream`, NOT JSON. Frames: `{delta}`, `{tool_status}`, `{choice_prompt}`, `{artifact}` (editor_component_draft / editor_goal_draft — the editor saves these as drafts through its own draft routes and previews them), `{error}`, then `[DONE]`. History is client-held. Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["messages","context"],"properties":{"messages":{"type":"array","description":"The conversation so far, oldest first, ending with the user turn"},"context":{"type":"object","description":"pagePath, pageTitle, and the targetable elements on the page (opaque refs)"}},"additionalProperties":false}}}},"security":[{"editorToken":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/editor/telemetry":{"post":{"operationId":"postEditorTelemetry","summary":"Record editor-usage events (batched)","tags":["editor"],"description":"Record editor-usage events (batched). Authenticate with a short-lived editor token (`Authorization: Bearer <token>`) issued to the on-site visual editor — not a session or an API key. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["events"],"description":"Editor lifecycle events (opened/selected/saved/published/errors) so the editor’s own funnel is measurable. Enum kinds + bounded scalar meta only.","properties":{"events":{"type":"array","description":"Up to 20 events per call."}},"additionalProperties":false}}},"description":"Editor lifecycle events (opened/selected/saved/published/errors) so the editor’s own funnel is measurable. Enum kinds + bounded scalar meta only."},"security":[{"editorToken":[]}],"responses":{"204":{"description":"Events recorded","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/locator-miss":{"post":{"operationId":"postLocatorMiss","summary":"Report unresolved snippet slot locators","tags":["ingest"],"description":"Report unresolved snippet slot locators. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["slots"],"description":"The published slot ids whose compound locator failed to resolve on the page.","properties":{"slots":{"type":"array","description":"Slot ids that missed (1–30 entries, each 1–128 chars). Deduplicated server-side.","items":{"type":"string"}}},"additionalProperties":true}}},"description":"The published slot ids whose compound locator failed to resolve on the page."},"security":[{"publicKey":[]}],"responses":{"204":{"description":"Miss reports recorded","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/slots/drift":{"post":{"operationId":"postSlotsDrift","summary":"Report generated versions that no longer match their region","tags":["ingest"],"description":"Report generated versions that no longer match their region. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sessionId","reports"],"description":"Regions whose markup changed since their generated versions were written.","properties":{"sessionId":{"type":"string","description":"The reporting session."},"reports":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"1–30 drift reports."}},"additionalProperties":true}}},"description":"Regions whose markup changed since their generated versions were written."},"security":[{"publicKey":[]}],"responses":{"204":{"description":"Recorded","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/section-map":{"post":{"operationId":"postSectionMap","summary":"Register no-code section semantic types","tags":["ingest"],"description":"Register no-code section semantic types. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["pageUrl","sections"],"description":"No-code section → semantic type mappings for one page.","properties":{"pageUrl":{"type":"string","description":"URL of the page the sections belong to (1–2048 chars)."},"sections":{"type":"array","minItems":1,"maxItems":200,"description":"Section mappings to upsert (1–200), one per section element on the page.","items":{"type":"object","required":["componentId","semanticType"],"properties":{"componentId":{"type":"string","description":"Section component id; must be in the no-code `nc-` namespace (1–128 chars)."},"semanticType":{"type":"string","enum":["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"],"description":"Semantic role assigned to the section."},"source":{"type":"string","enum":["markup","auto"],"description":"Client-side provenance: explicit data-sentient-type markup vs heuristic/served map. Optional; defaults to auto."},"locator":{"type":"object","description":"Compound locator for this section. The server hashes it into a stable section_key — the same identity the crawler derives for the same section. Omit when nothing resolves uniquely.","additionalProperties":true},"observation":{"type":"object","description":"Client-sensor features for server-side topic classification of pages the crawler cannot fetch: tag, id/class, heading text, text length, action count, ARIA role, and which shipped content patterns matched. Never contains body text.","additionalProperties":true}},"additionalProperties":true}}},"additionalProperties":true}}},"description":"No-code section → semantic type mappings for one page."},"security":[{"publicKey":[]}],"responses":{"204":{"description":"Section mappings upserted","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/personas":{"get":{"operationId":"getPersonas","summary":"List the project's active persona vocabulary","tags":["ingest"],"description":"List the project's active persona vocabulary. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"publicKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"personas":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Vocabulary key — what decisions and CSS selectors key on."},"displayName":{"type":"string"}},"additionalProperties":false}},"discovered":{"type":"array","description":"Members of the latest DISCOVERED shadow set (persona auto-discovery), if any. Shadow sets never serve until promotion, so these are display-only: tooling may show them as \"not serving yet\" but must not offer to force them.","items":{"type":"object","properties":{"key":{"type":"string"},"displayName":{"type":"string"}},"additionalProperties":false}}},"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/explain":{"post":{"operationId":"postExplain","summary":"Simulate a decision for a persona without recording events","tags":["ingest"],"description":"Simulate a decision for a persona without recording events. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Simulation request. At least one of `sections` or `slots` must be non-empty. Read-only: no events are recorded.","properties":{"persona":{"type":"string","description":"Persona to simulate: a key or alias from the project's persona vocabulary (legacy labels resolve too). An unrecognized value simulates the default experience and is echoed back with `recognized: false`. Omitted simulates the pre-portrait state."},"sections":{"type":"array","description":"Page sections to simulate a layout order for.","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"Section/component id."}},"additionalProperties":true}},"components":{"type":"array","description":"Components to simulate a variant assignment for (the first declared variant is returned).","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"Component id."},"variantIds":{"type":"array","items":{"type":"string"},"description":"Candidate variant ids; the first is used in the simulated assignment."}},"additionalProperties":true}},"slots":{"type":"array","description":"Declared slots to simulate arms for (max 30).","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"Slot id."},"arms":{"type":"array","items":{"type":"string"},"description":"Candidate arm labels (2–12). Provide `arms` OR `dims`, not both."},"dims":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"description":"Named dimensions, each with 2–6 values (1–4 dims; value product ≤ 64). Provide `dims` OR `arms`."},"baseline":{"description":"Declared baseline: an arm string, or a per-dimension { dim: value } map."}},"additionalProperties":true}},"force":{"type":"object","additionalProperties":{"type":"string"},"description":"Registry mode only: force specific slots to specific arms (slotId → armId), for read-only preview of a variant that is not the one currently served. An arm outside the slot's declared space is ignored."},"includeDrafts":{"type":"boolean","description":"Registry mode only: also resolve draft (unpublished) slots, from their draft config. Preview-only — persona simulation must mirror what actually serves, so this never changes serving behaviour. Honoured only together with a valid `previewToken`; without one the request is answered from published slots only."},"previewToken":{"type":"string","description":"Short-lived preview (or on-site editor) token for THIS project, minted by the management API. Required for `includeDrafts` — the public key alone ships in page source and must not expose unpublished copy."},"slotsFrom":{"type":"string","enum":["request","registry"],"description":"Slot source. 'registry' simulates the project's PUBLISHED slot_definitions (no client declaration needed) — used by the no-code snippet's persona preview. Defaults to 'request'."}},"additionalProperties":true}}},"description":"Simulation request. At least one of `sections` or `slots` must be non-empty. Read-only: no events are recorded."},"security":[{"publicKey":[]}],"responses":{"200":{"description":"Simulated decision for the requested persona (read-only, event-free)","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"layoutOrder":{"type":"array","items":{"type":"string"}},"assignments":{"type":"object","additionalProperties":true},"persona":{"type":"string"},"personaDisplay":{"type":"string","description":"Human display name of the simulated persona (vocabulary display name when recognized)."},"recognized":{"type":"boolean","description":"Whether the requested persona resolved against the project's vocabulary (key, alias, or legacy label). False means the default/pre-portrait experience was simulated instead."},"reasons":{"type":"array","items":{"type":"object","properties":{"section":{"type":"string"},"reason":{"type":"string"},"source":{"type":"string"}},"additionalProperties":true}},"personaAttributes":{"type":"object","additionalProperties":true},"slots":{"type":"object","additionalProperties":true},"slotConfig":{"type":"object","additionalProperties":true},"palette":{"type":"object","additionalProperties":true}},"additionalProperties":true,"description":"Simulated decision for the requested persona (read-only, event-free)"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/layout-stats":{"get":{"operationId":"getLayoutStats","summary":"Per-persona learned layout performance","tags":["ingest"],"description":"Per-persona learned layout performance. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"publicKey":[]}],"responses":{"200":{"description":"Learned layout weights per persona","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"layouts":{"type":"array","items":{"type":"object","properties":{"persona":{"type":"string"},"layoutOrder":{"type":"array","items":{"type":"string"}},"pulls":{"type":"number"},"avgReward":{"type":"number"},"totalReward":{"type":"number"},"alpha":{"type":"number"},"beta":{"type":"number"}},"additionalProperties":true}}},"additionalProperties":true,"description":"Learned layout weights per persona"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/guardrails/{componentId}":{"put":{"operationId":"putGuardrailsByComponentId","summary":"Set component guardrail threshold and min observations","tags":["mgmt"],"description":"Set component guardrail threshold and min observations. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Guardrail configuration for the component. Both fields have defaults if omitted.","properties":{"guardrailThreshold":{"type":"number","description":"Maximum tolerated relative drop vs the best variant, in (0, 1]. Defaults to 0.2. A variant is auto-paused only once its rate is shown to be lower by MORE than this, using bounds that stay valid at every 5-minute check (CONTRACTS §5)."},"minObservations":{"type":"integer","description":"Minimum exposures a variant (and the variant it is compared with) must accumulate before the guardrail can pause it. Must be >= 1. Only delays a pause; it is not what makes a pause sound."}},"additionalProperties":true}}},"description":"Guardrail configuration for the component. Both fields have defaults if omitted."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"componentId","required":true,"description":"Component identifier the guardrail applies to."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/guardrails/{componentId}/unpause":{"post":{"operationId":"postGuardrailsByComponentIdUnpause","summary":"Unpause guardrail-paused variants for a component","tags":["mgmt"],"description":"Unpause guardrail-paused variants for a component. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["variantIds"],"description":"The variants to unpause for this component.","properties":{"variantIds":{"type":"array","description":"Variant ids to clear the paused state on. Must be non-empty.","items":{"type":"string"}}},"additionalProperties":true}}},"description":"The variants to unpause for this component."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"componentId","required":true,"description":"Component identifier the guardrail applies to."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/decision-log":{"get":{"operationId":"getDecisionLog","summary":"Recent decisions for a session","tags":["ingest"],"description":"Recent decisions for a session. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"publicKey":[]}],"responses":{"200":{"description":"Recent decision log entries for the session","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"decisions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"persona":{"type":"string"},"confidence":{"type":"number"},"layoutOrder":{"type":"array","items":{"type":"string"}},"assignments":{"type":"object","additionalProperties":true},"shadowOnly":{"type":"boolean"},"reason":{"type":"string"}},"additionalProperties":true}}},"additionalProperties":true,"description":"Recent decision log entries for the session"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/goals":{"post":{"operationId":"postGoals","summary":"Record a goal/conversion event","tags":["ingest"],"description":"Record a goal/conversion event. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sessionId","name","goalId"],"description":"A goal/conversion event to attribute to a session.","properties":{"sessionId":{"type":"string","description":"Session id the goal is attributed to (the _snt_uid cookie)."},"name":{"type":"string","description":"Goal name (e.g. \"signup\", \"checkout\")."},"goalId":{"type":"string","description":"Client-generated UUID; deduplicates retries (ON CONFLICT DO NOTHING)."},"metadata":{"type":"object","additionalProperties":true,"description":"Arbitrary event metadata. Defaults to {}."},"weight":{"type":"number","description":"Goal value/weight in [0,1]. Defaults to 1."},"stepIndex":{"type":"integer","description":"Funnel step index (0-based). Defaults to 0."},"value":{"type":"number","description":"Monetary value of this conversion in the project currency (e.g. order total)."},"currency":{"type":"string","description":"ISO-4217 code, only when it differs from the project currency."},"externalId":{"type":"string","description":"Merchant order/transaction id. Duplicate (goal name, externalId) submissions are dropped."}},"additionalProperties":true}}},"description":"A goal/conversion event to attribute to a session."},"security":[{"publicKey":[]}],"responses":{"202":{"description":"Goal event accepted for processing","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"integer","description":"Number of goal events accepted"}},"additionalProperties":true,"description":"Goal event accepted for processing"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/attributions":{"post":{"operationId":"postAttributions","summary":"Bind a cart/checkout token to a session","tags":["ingest"],"description":"Bind a cart/checkout token to a session. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sessionId","token"],"description":"Binds a commerce cart/checkout token to the visitor session so server-side orders can be attributed.","properties":{"sessionId":{"type":"string","description":"Session id the token belongs to (the _snt_uid cookie)."},"token":{"type":"string","description":"Cart or checkout token from the commerce platform."}},"additionalProperties":true}}},"description":"Binds a commerce cart/checkout token to the visitor session so server-side orders can be attributed."},"security":[{"publicKey":[]}],"responses":{"202":{"description":"Binding accepted","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"integer","description":"Number of bindings accepted"}},"additionalProperties":true,"description":"Binding accepted"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/conversions":{"post":{"operationId":"postConversions","summary":"Record a server-truth order/conversion","tags":["ingest"],"description":"Record a server-truth order/conversion. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["externalId","value","currency"],"description":"A server-side order. Idempotent per externalId; retry on 500. Auth: sk_ bearer, or pk_ bearer plus X-Sentient-Signature (hex SHA-256 HMAC of the raw body with your conversions secret).","properties":{"externalId":{"type":"string","description":"Merchant order/transaction id — the idempotency key."},"value":{"type":"number","description":"Order total in `currency`."},"currency":{"type":"string","description":"ISO-4217 code."},"goalName":{"type":"string","description":"Goal to credit (default 'purchase')."},"occurredAt":{"type":"string","description":"ISO timestamp the order happened; implausible values fall back to receive time."},"attribution":{"type":"object","description":"Optional attribution hints, resolved in order: sessionId (if owned), cartToken/checkoutToken via prior /v1/attributions bindings.","additionalProperties":true}},"additionalProperties":true}}},"description":"A server-side order. Idempotent per externalId; retry on 500. Auth: sk_ bearer, or pk_ bearer plus X-Sentient-Signature (hex SHA-256 HMAC of the raw body with your conversions secret)."},"security":[{"publicKey":[]}],"responses":{"202":{"description":"Conversion recorded","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"boolean"},"attributed":{"type":"boolean","description":"True when the order landed on a visitor session (trains + funnels); false = reporting-only."},"duplicate":{"type":"boolean","description":"Set on a replayed externalId (no new write)."}},"additionalProperties":true,"description":"Conversion recorded"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/refund":{"post":{"operationId":"postRefund","summary":"Record a refund against a recorded order","tags":["ingest"],"description":"Record a refund against a recorded order. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["externalId"],"description":"Nets a refund against the order recorded under externalId. Amount defaults to the full remaining (clamped so revenue never goes negative). Idempotent per refundId; retry on 500. Auth: sk_ bearer, or pk_ bearer plus X-Sentient-Signature.","properties":{"externalId":{"type":"string","description":"The refunded order id (as sent to /v1/conversions)."},"amount":{"type":"number","description":"Refund amount; omit for a full refund of the remaining balance."},"currency":{"type":"string","description":"ISO-4217 code (informational)."},"goalName":{"type":"string","description":"Goal the order credited (default 'purchase')."},"refundId":{"type":"string","description":"The platform's refund id — makes webhook retries idempotent."}},"additionalProperties":true}}},"description":"Nets a refund against the order recorded under externalId. Amount defaults to the full remaining (clamped so revenue never goes negative). Idempotent per refundId; retry on 500. Auth: sk_ bearer, or pk_ bearer plus X-Sentient-Signature."},"security":[{"publicKey":[]}],"responses":{"202":{"description":"Refund netted","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"boolean"},"netted":{"type":"number","description":"The amount actually netted (0 on a deduped retry)."}},"additionalProperties":true,"description":"Refund netted"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/provision/shopify":{"post":{"operationId":"postProvisionShopify","summary":"Provision Shopify commerce defaults","tags":["mgmt"],"description":"Idempotently creates the purchase goal and the template checkout funnel for a Shopify install, and allowlists the shop’s storefront origins. Requires the project secret key (sk_). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"shopDomain":{"type":"string","description":"The shop’s myshopify.com host, e.g. my-store.myshopify.com."},"primaryDomain":{"type":"string","description":"The shop’s primary (custom) domain host, if different."},"subscriptionObserved":{"type":"string","enum":["none"],"description":"The app just read the shop’s subscriptions from Shopify and found none active."}},"additionalProperties":true}}}},"security":[{"secretKey":[]}],"responses":{"200":{"description":"Defaults provisioned (or already present)","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"goalId":{"type":"string"},"funnelId":{"type":"string"},"binding":{"type":"string","enum":["live","disconnected","detached"],"description":"The shop's connection to this project after the call (with the connector secret and a shop domain only)."}},"additionalProperties":true,"description":"Defaults provisioned (or already present)"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/provision/shopify/plan":{"post":{"operationId":"postProvisionShopifyPlan","summary":"Sync a Shopify-billed plan","tags":["mgmt"],"description":"Sets the project owner’s plan from the shop’s Shopify Managed Pricing subscription. Requires the project secret key (sk_) plus the connector shared secret. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plan"],"properties":{"plan":{"type":"string","description":"Plan id: free, or a self-serve paid plan (starter, growth, scale)."},"shopDomain":{"type":"string","description":"The shop’s myshopify.com host, for the audit trail."},"disconnect":{"type":"boolean","description":"True only for an uninstall (not a cancellation): also hands the billing rail back to self-serve."},"ended":{"type":"boolean","description":"The subscription ended (cancelled, expired, declined, frozen), as opposed to an active free plan."},"status":{"type":"string","description":"The subscription status (ACTIVE, FROZEN, CANCELLED, EXPIRED, DECLINED); preferred over `ended`."},"subscriptionId":{"type":"string","description":"Shopify AppSubscription GID the event is about."},"subscriptionUpdatedAt":{"type":"string","description":"The event’s app_subscription.updated_at (ISO 8601). Older events than the last applied one are ignored."}},"additionalProperties":true}}}},"security":[{"secretKey":[]}],"responses":{"200":{"description":"Plan applied","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"plan":{"type":"string"}},"additionalProperties":true,"description":"Plan applied"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/origin-check":{"get":{"operationId":"getOriginCheck","summary":"Check a publishable key against a browser origin","tags":["ingest"],"description":"Returns 200 when the publishable key accepts requests from the request’s Origin, and the same 403 `origin_not_allowed` the ingest endpoints return when it does not. Side-effect free: nothing is recorded. Intended for install-verification surfaces. Authenticate with a publishable key (`Authorization: Bearer pk_…`) from an allowed origin. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"publicKey":[]}],"responses":{"200":{"description":"The key accepts this origin","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":false,"description":"The key accepts this origin"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/webhook/stripe":{"post":{"operationId":"postWebhookStripe","summary":"Stripe webhook receiver","tags":["infra"],"description":"Receives Stripe events for subscription and payment lifecycle. Called by Stripe, not by API consumers. The request is authenticated by the `Stripe-Signature` header against the endpoint signing secret — not by an API key — so it carries no `security` requirement from this spec. Answers `400` on a missing or invalid signature and `200` once the event is accepted; Stripe retries on any non-2xx. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/me":{"get":{"operationId":"getMgmtMe","summary":"Caller's role and billing-owner flag","tags":["mgmt"],"description":"Caller's role and billing-owner flag. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"projectId","required":false,"description":"Answer for this project (partner-manager grants change the role)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string"},"isBillingOwner":{"type":"boolean"},"viaGrant":{"type":"boolean"},"partnerAccounts":{"type":"number"}},"additionalProperties":true}}}}}}},"/v1/mgmt/team":{"get":{"operationId":"getMgmtTeam","summary":"Team management or member view","tags":["mgmt"],"description":"Team management or member view. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string"},"seatLimit":{"type":"number"},"seatCount":{"type":"number"},"isBillingOwner":{"type":"boolean"}},"additionalProperties":true}}}}}},"patch":{"operationId":"patchMgmtTeam","summary":"Rename the workspace","tags":["mgmt"],"description":"Rename the workspace. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"description":"New workspace name.","properties":{"name":{"type":"string","description":"New workspace name. Trimmed; must be 1–60 characters."}},"additionalProperties":true}}},"description":"New workspace name."},"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/team/activity":{"get":{"operationId":"getMgmtTeamActivity","summary":"Account-level team activity (admins only)","tags":["mgmt"],"description":"Account-level team activity (admins only). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/team/invite":{"post":{"operationId":"postMgmtTeamInvite","summary":"Invite a team member","tags":["mgmt"],"description":"Invite a team member. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"description":"The member to invite. Only `email` is required; `role` defaults to editor.","properties":{"email":{"type":"string","description":"Email address to invite."},"role":{"type":"string","enum":["admin","editor","viewer"],"description":"Member role — one of 'admin', 'editor', 'viewer'. Defaults to 'editor'."},"projectIds":{"type":"array","items":{"type":"string"},"description":"Project UUIDs the member may see (editors/viewers only; ignored for admins). Capped at 200."},"teamName":{"type":"string","description":"Workspace name to set if the workspace has none yet (or still has the default name). Never renames an already-named workspace. Max 60 characters."}},"additionalProperties":true}}},"description":"The member to invite. Only `email` is required; `role` defaults to editor."},"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"resent":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/team/members/{memberId}":{"patch":{"operationId":"patchMgmtTeamMembersByMemberId","summary":"Change a member's role","tags":["mgmt"],"description":"Change a member's role. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["role"],"description":"The member's new role.","properties":{"role":{"type":"string","enum":["admin","editor","viewer"],"description":"New role — one of 'admin', 'editor', 'viewer'."}},"additionalProperties":true}}},"description":"The member's new role."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"memberId","required":true,"description":"Team member row UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteMgmtTeamMembersByMemberId","summary":"Remove a team member","tags":["mgmt"],"description":"Remove a team member. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"memberId","required":true,"description":"Team member row UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/team/members/{memberId}/projects":{"put":{"operationId":"putMgmtTeamMembersByMemberIdProjects","summary":"Replace a member's project visibility","tags":["mgmt"],"description":"Replace a member's project visibility. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectIds"],"description":"The member's full set of project visibility grants; replaces any existing grants.","properties":{"projectIds":{"type":"array","items":{"type":"string"},"description":"Project UUIDs the member may see. Only ids belonging to the account take effect."}},"additionalProperties":true}}},"description":"The member's full set of project visibility grants; replaces any existing grants."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"memberId","required":true,"description":"Team member row UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/team/staff/{userId}":{"delete":{"operationId":"deleteMgmtTeamStaffByUserId","summary":"Revoke a partner manager's access to this account","tags":["mgmt"],"description":"Revoke a partner manager's access to this account. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"userId","required":true,"description":"Partner manager Clerk user id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/team/leave":{"post":{"operationId":"postMgmtTeamLeave","summary":"Leave your team","tags":["mgmt"],"description":"Leave your team. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/join/preview":{"get":{"operationId":"getMgmtJoinPreview","summary":"Preview an invite before accepting","tags":["mgmt"],"description":"Preview an invite before accepting. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"team_name":{"type":"string"},"invited_email":{"type":"string"},"status":{"type":"string"},"expired":{"type":"boolean"},"ownedProjects":{"type":"number"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/join":{"post":{"operationId":"postMgmtJoin","summary":"Accept an invite via token","tags":["mgmt"],"description":"Accept an invite via token. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"description":"The invite token from the invitation email.","properties":{"token":{"type":"string","description":"Raw invite token delivered by email."}},"additionalProperties":true}}},"description":"The invite token from the invitation email."},"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/staff-access/accounts":{"get":{"operationId":"getMgmtStaffAccessAccounts","summary":"Accounts the caller can work in as a partner manager","tags":["mgmt"],"description":"Accounts the caller can work in as a partner manager. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects":{"get":{"operationId":"getMgmtProjects","summary":"List visible projects","tags":["mgmt"],"description":"List visible projects. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Projects the caller can see","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Project UUID"},"name":{"type":"string"},"context_type":{"type":"string"}},"additionalProperties":true},"description":"Projects the caller can see"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"postMgmtProjects","summary":"Create a project","tags":["mgmt"],"description":"Create a project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"description":"The project to create. Only `name` is required.","properties":{"name":{"type":"string","description":"Human-readable project name."},"contextType":{"type":"string","description":"Site type — one of 'saas', 'ecommerce', 'marketing', 'landing', 'internal'. Defaults to 'saas'."},"origin":{"type":"string","description":"Production site origin (e.g. https://app.example.com) to allow-list for event ingest. Localhost dev origins are seeded automatically."},"framework":{"type":"string","description":"Target framework — one of 'next', 'react', 'shopify', 'core' (legacy 'next-app'/'next-pages' still accepted). Defaults to 'next'."},"dayZeroGeneration":{"type":"boolean","description":"Have AI write first versions of the site’s regions as soon as they are known (site scan / SDK registration). Forces review mode on: nothing publishes without approval."},"serverKey":{"type":"boolean","description":"Set false with framework 'shopify' to skip minting the sk_ (the zero-key connect mints its own pair)."},"accountOwnerId":{"type":"string","description":"Create in another account (a partner manager acting for an agency). Requires an account-wide admin staff_access grant on it and a dashboard session; otherwise 404. No sk_ is minted on this path."}},"additionalProperties":true}}},"description":"The project to create. Only `name` is required."},"security":[{"secretKey":[]}],"responses":{"201":{"description":"Project created","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["id","apiKey"],"properties":{"id":{"type":"string","description":"New project UUID"},"apiKey":{"type":"string","description":"pk_ public key for the SDK"},"serverKey":{"type":"string","description":"sk_ server key, returned only for framework 'shopify' — the Shopify app needs one to provision the purchase goal and forward orders, so it is minted up front instead of sending the merchant to Settings. Shown exactly once, like the public key."}},"description":"Project created"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/demo":{"post":{"operationId":"postMgmtProjectsDemo","summary":"Provision (or return) the account's seeded demo project","tags":["mgmt"],"description":"Provision (or return) the account's seeded demo project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"created":{"type":"boolean"}},"required":["id","created"],"additionalProperties":false}}}},"201":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"created":{"type":"boolean"}},"required":["id","created"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}":{"get":{"operationId":"getMgmtProjectsById","summary":"Get project details","tags":["mgmt"],"description":"Get project details. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Project details","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"plan":{"type":"string"},"context_type":{"type":"string","description":"saas | ecommerce | marketing | landing | internal"},"shadow_mode":{"type":"boolean"},"holdout_rate":{"type":"number"},"pooled_serving":{"type":"boolean","description":"Persona-pooled serving (Settings → Persona pooling)."},"key_prefix":{"type":"string","nullable":true}},"additionalProperties":true,"description":"Project details"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"patchMgmtProjectsById","summary":"Update project settings","tags":["mgmt"],"description":"Update project settings. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Fields to update. Omit any field to leave it unchanged.","properties":{"goalTarget":{"type":"number","description":"Target number of conversions for the primary goal. Must be positive."},"shadowMode":{"type":"boolean","description":"When true, the optimizer observes traffic but does not alter the UI."},"contextType":{"type":"string","description":"Site type — one of 'saas', 'ecommerce', 'marketing', 'landing', 'internal'. Sets the industry benchmark used until the project's own conversion rate is measured."},"holdoutRate":{"type":"number","description":"Fraction of visitors held back as a control group, in [0, 1]. 0 disables the holdout."},"framework":{"type":"string","description":"Target framework — one of 'next', 'react', 'shopify', 'core' (legacy 'next-app'/'next-pages' still accepted)."},"confirmHoldout":{"type":"boolean","description":"Marks the control-group wizard step as seen. Set to true when the user continues past it."},"weeklyDigest":{"type":"boolean","description":"Whether this project sends the weekly evidence digest email. Defaults to true; false opts the project out."},"wizard":{"type":"object","description":"Onboarding-wizard acknowledgements. Each flag is set-once and write-only — sending true stamps the decision's timestamp; false is ignored (a teammate cannot un-skip a step someone else skipped).","properties":{"skipped":{"type":"boolean","description":"\"Skip to dashboard\" — leave the guided wizard."},"componentSkipped":{"type":"boolean","description":"The component step was passed over."},"goalAcked":{"type":"boolean","description":"The goal step's explicit Continue was clicked."},"seen":{"type":"boolean","description":"The wizard was shown for this project (gates the setup-pulse survey)."},"resume":{"type":"boolean","description":"\"Resume guided setup\" — clears an earlier skip so the wizard shows again."}},"additionalProperties":false},"reportingTimezone":{"type":"string","description":"IANA timezone (e.g. 'Europe/Madrid') used to cut day/week boundaries in every reporting window. Validated against the runtime zone list; invalid values 400 with invalid_timezone. Default 'UTC'."}},"additionalProperties":true}}},"description":"Fields to update. Omit any field to leave it unchanged."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteMgmtProjectsById","summary":"Delete a project","tags":["mgmt"],"description":"Delete a project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["confirmName"],"description":"Delete confirmation. `confirmName` must exactly match the project name.","properties":{"confirmName":{"type":"string","description":"Must equal the target project's name, as a delete confirmation."}},"additionalProperties":true}}},"description":"Delete confirmation. `confirmName` must exactly match the project name."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/proof-window":{"post":{"operationId":"postMgmtProjectsByIdProofWindow","summary":"Open a proof window (temporarily raise the control group)","tags":["mgmt"],"description":"Recomputes the offer server-side and refuses anything proofWindowOffer would not have offered. The window closes automatically when a verdict lands or the horizon lapses. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"The stored proof-window state","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"The stored proof-window state"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/keys":{"get":{"operationId":"getMgmtKeys","summary":"List API keys","tags":["mgmt"],"description":"List API keys. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"project_id":{"type":"string"},"project_name":{"type":"string"},"key_prefix":{"type":"string"},"revoked":{"type":"boolean"},"public_value":{"type":"string","nullable":true}},"additionalProperties":true}}}}}}},"post":{"operationId":"postMgmtKeys","summary":"Rotate or add a project public key","tags":["mgmt"],"description":"Rotate or add a project public key. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId"],"description":"Which project to issue a new pk_ public key for.","properties":{"projectId":{"type":"string","description":"UUID of the project whose active pk_ keys are revoked and replaced."},"keepExisting":{"type":"boolean","description":"Issue an additional pk_ without revoking the active ones (default false = rotate)."}},"additionalProperties":true}}},"description":"Which project to issue a new pk_ public key for."},"security":[{"secretKey":[]}],"responses":{"201":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"type":"string"},"prefix":{"type":"string"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/keys/server":{"post":{"operationId":"postMgmtKeysServer","summary":"Issue a server key","tags":["mgmt"],"description":"Issue a server key. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId"],"description":"Which project to issue an sk_ server key for. Every plan, including Free, can issue one; the key is scoped to that project only.","properties":{"projectId":{"type":"string","description":"UUID of the project. Any existing sk_ key for the project is revoked first."}},"additionalProperties":true}}},"description":"Which project to issue an sk_ server key for. Every plan, including Free, can issue one; the key is scoped to that project only."},"security":[{"secretKey":[]}],"responses":{"201":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"type":"string"},"prefix":{"type":"string"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/keys/{id}/revoke":{"post":{"operationId":"postMgmtKeysByIdRevoke","summary":"Revoke a key","tags":["mgmt"],"description":"Revoke a key. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"UUID of the api_keys row to revoke."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/origins":{"get":{"operationId":"getMgmtProjectsByIdOrigins","summary":"List allowed origins","tags":["mgmt"],"description":"List allowed origins. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"origins":{"type":"array","items":{"type":"string"}}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"postMgmtProjectsByIdOrigins","summary":"Add an allowed origin","tags":["mgmt"],"description":"Add an allowed origin. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["origin"],"properties":{"origin":{"type":"string","description":"The origin to add or remove (e.g. https://app.example.com)."}},"additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"origins":{"type":"array","items":{"type":"string"}}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteMgmtProjectsByIdOrigins","summary":"Remove an allowed origin","tags":["mgmt"],"description":"Remove an allowed origin. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["origin"],"properties":{"origin":{"type":"string","description":"The origin to add or remove (e.g. https://app.example.com)."}},"additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"origins":{"type":"array","items":{"type":"string"}}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/personas":{"get":{"operationId":"getMgmtProjectsByIdPersonas","summary":"List the project persona vocabulary","tags":["mgmt"],"description":"List the project persona vocabulary. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string"},"version":{"type":"number"},"members":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"postMgmtProjectsByIdPersonas","summary":"Add a persona to the vocabulary","tags":["mgmt"],"description":"Add a persona to the vocabulary. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["key"],"properties":{"key":{"type":"string","description":"Slug key, e.g. \"admin\". Lowercase letters/digits/_/-, max 32 chars."},"displayName":{"type":"string","description":"Human-facing name. Defaults to the key."},"description":{"type":"string"}},"additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string"},"version":{"type":"number"},"members":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/personas/discovered":{"get":{"operationId":"getMgmtProjectsByIdPersonasDiscovered","summary":"The discovered candidate persona set (shadow), with evidence and readiness","tags":["mgmt"],"description":"The discovered candidate persona set (shadow), with evidence and readiness. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"set":{"type":"object","additionalProperties":true,"nullable":true},"readiness":{"type":"object","additionalProperties":true}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/personas/promotion":{"get":{"operationId":"getMgmtProjectsByIdPersonasPromotion","summary":"Whether the discovered set can be promoted, and what would change","tags":["mgmt"],"description":"Whether the discovered set can be promoted, and what would change. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/personas/promote":{"post":{"operationId":"postMgmtProjectsByIdPersonasPromote","summary":"Promote the discovered set to serving (evidence-gated, explicit)","tags":["mgmt"],"description":"Promote the discovered set to serving (evidence-gated, explicit). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mapping":{"type":"object","additionalProperties":{"type":"string"},"description":"Old key → new key for segments considered the same audience; mapped keys are aliased and their history re-pooled."}},"additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/personas/rollback":{"post":{"operationId":"postMgmtProjectsByIdPersonasRollback","summary":"Demote the active discovered set and restore the previous one","tags":["mgmt"],"description":"Demote the active discovered set and restore the previous one. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/personas/adoption":{"get":{"operationId":"getMgmtProjectsByIdPersonasAdoption","summary":"Declared-persona adoption: coverage split + unrecognized declarations","tags":["mgmt"],"description":"Declared-persona adoption: coverage split + unrecognized declarations. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"windowDays":{"type":"number"},"coverage":{"type":"object","properties":{"declared":{"type":"number"},"inferred":{"type":"number"},"none":{"type":"number"}},"additionalProperties":true},"unrecognized":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"count":{"type":"number"}},"additionalProperties":true}},"overflowCount":{"type":"number"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/personas/{key}":{"patch":{"operationId":"patchMgmtProjectsByIdPersonasByKey","summary":"Rename, retire, or reactivate a persona","tags":["mgmt"],"description":"Rename, retire, or reactivate a persona. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"displayName":{"type":"string"},"description":{"type":"string"},"newKey":{"type":"string","description":"Rename: the old key becomes an alias so CSS/history keep resolving."},"status":{"type":"string","enum":["active","retired"]}},"additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"key","required":true,"description":"Current member key."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string"},"version":{"type":"number"},"members":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/variants/restore":{"post":{"operationId":"postMgmtProjectsByIdVariantsRestore","summary":"Restore a variant to active","tags":["mgmt"],"description":"Restore a variant to active. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["componentId","variantId"],"description":"Targets a single variant within a component.","properties":{"componentId":{"type":"string","description":"Component id the variant belongs to."},"variantId":{"type":"string","description":"Variant id to act on."}},"additionalProperties":true}}},"description":"Targets a single variant within a component."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/variants/pause":{"post":{"operationId":"postMgmtProjectsByIdVariantsPause","summary":"Pause a variant","tags":["mgmt"],"description":"Pause a variant. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["componentId","variantId"],"description":"Targets a single variant within a component.","properties":{"componentId":{"type":"string","description":"Component id the variant belongs to."},"variantId":{"type":"string","description":"Variant id to act on."}},"additionalProperties":true}}},"description":"Targets a single variant within a component."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/variants/retire":{"post":{"operationId":"postMgmtProjectsByIdVariantsRetire","summary":"Retire (archive) an active variant","tags":["mgmt"],"description":"Retire (archive) an active variant. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["componentId","variantId"],"description":"Targets a single variant within a component.","properties":{"componentId":{"type":"string","description":"Component id the variant belongs to."},"variantId":{"type":"string","description":"Variant id to act on."}},"additionalProperties":true}}},"description":"Targets a single variant within a component."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/variants":{"post":{"operationId":"postMgmtProjectsByIdVariants","summary":"Create a draft variant","tags":["mgmt"],"description":"Create a draft variant. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["componentId"],"description":"The draft variant to create. Only `componentId` is required.","properties":{"componentId":{"type":"string","description":"Component id to attach the new variant to."},"displayName":{"type":"string","description":"Human-readable label for the variant."},"content":{"type":"string","description":"Variant content/body stored on the preview row."}},"additionalProperties":true}}},"description":"The draft variant to create. Only `componentId` is required."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"201":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"variantId":{"type":"string"},"status":{"type":"string"},"displayName":{"type":"string","nullable":true}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"patchMgmtProjectsByIdVariants","summary":"Update a managed variant","tags":["mgmt"],"description":"Update a managed variant. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["componentId","variantId"],"description":"Identifies the managed variant and the fields to change. Omit a field to leave it unchanged.","properties":{"componentId":{"type":"string","description":"Component id the variant belongs to."},"variantId":{"type":"string","description":"Variant id to update."},"displayName":{"type":"string","description":"New human-readable label."},"content":{"type":"string","description":"New variant content/body."},"status":{"type":"string","enum":["draft","active"],"description":"New lifecycle status — one of 'draft' or 'active'."}},"additionalProperties":true}}},"description":"Identifies the managed variant and the fields to change. Omit a field to leave it unchanged."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteMgmtProjectsByIdVariants","summary":"Delete a draft variant","tags":["mgmt"],"description":"Delete a draft variant. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["componentId","variantId"],"description":"Targets a single variant within a component.","properties":{"componentId":{"type":"string","description":"Component id the variant belongs to."},"variantId":{"type":"string","description":"Variant id to act on."}},"additionalProperties":true}}},"description":"Targets a single variant within a component."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/previews":{"get":{"operationId":"getMgmtProjectsByIdPreviews","summary":"List component variant previews","tags":["mgmt"],"description":"List component variant previews. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"operationId":"putMgmtProjectsByIdPreviews","summary":"Batch upsert variant previews","tags":["mgmt"],"description":"Batch upsert variant previews. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["items"],"description":"Batch of preview rows to upsert. `items` must be non-empty.","properties":{"items":{"type":"array","description":"Preview items; each requires componentId and variantId.","items":{"type":"object","required":["componentId","variantId"],"properties":{"componentId":{"type":"string","description":"Component id."},"variantId":{"type":"string","description":"Variant id."},"displayName":{"type":"string","description":"Human-readable label."},"previewUrl":{"type":"string","description":"URL to a rendered preview."}},"additionalProperties":true}}},"additionalProperties":true}}},"description":"Batch of preview rows to upsert. `items` must be non-empty."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"updated":{"type":"number"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/components":{"get":{"operationId":"getMgmtProjectsByIdComponents","summary":"List component aggregates for a project","tags":["mgmt"],"description":"List component aggregates for a project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default all). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Keyset cursor (an opaque component_id). Returns components ordered after it; preferred over page."},{"schema":{"type":"string"},"in":"query","name":"limit","required":false,"description":"Max components per page (1–1000, default 50)."},{"schema":{"type":"string","deprecated":true},"in":"query","name":"page","required":false,"description":"Deprecated: 1-based page index. Use cursor for stable forward pagination."},{"schema":{"type":"string"},"in":"query","name":"includeArchived","required":false,"description":"Set to '1'/'true' to include archived components (each flagged `archived: true`). Omitted by default."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Paginated component aggregation","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"integer"},"page":{"type":"integer"},"limit":{"type":"integer"},"archivedComponentIds":{"type":"array","items":{"type":"string"},"description":"Components hidden by an operator. Returned whether or not includeArchived is set, so a client can both count them and keep them out of a live stream merge."},"nextCursor":{"type":"string","nullable":true,"description":"Keyset cursor for the next page, or null on the last page."},"components":{"type":"array","items":{"type":"object","properties":{"control_id":{"type":"string","nullable":true,"description":"The baseline arm every variant's evidence_state is measured against: 'control' when declared, else the alphabetically-first variant id. Null when the component has no variants."},"baseline_explicit":{"type":"boolean","description":"True only when an arm is literally named 'control'. False means the baseline is an arbitrary (alphabetical) pick — say \"vs <control_id>\", never \"vs control\"."},"variants":{"type":"array","items":{"type":"object","properties":{"evidence_state":{"type":"string","nullable":true,"description":"ALL-TIME verdict vs control_id on the arm's DIRECT-reward posterior (variant_weights, propagated credit from neighbouring components excluded; not windowed). The Reliability column and the Promote gate read this. Null on the control."},"window_evidence":{"type":"object","nullable":true,"additionalProperties":true,"description":"WINDOWED verdict vs control_id on the session conversion rate this row prints (conversions ÷ exposed_sessions, human sessions in the selected range): { state, probBeatsControl, threshold: { moderate, strong, minSample }, sample, controlSample, ageDays, method }. `sample`/`controlSample` are exposed sessions; both need minSample; bars are Bonferroni-corrected over the non-control arms exposed in the window. Colour or call the lift column \"ahead/behind\" from this, never from evidence_state. Null on the control."}},"additionalProperties":true}}},"additionalProperties":true}}},"additionalProperties":true,"description":"Paginated component aggregation"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/components/{componentId}/promote":{"post":{"operationId":"postMgmtProjectsByIdComponentsByComponentIdPromote","summary":"Promote a variant for a component","tags":["mgmt"],"description":"Promote a variant for a component. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["variantId"],"description":"The variant to promote for this component.","properties":{"variantId":{"type":"string","description":"Variant to serve as the default. Promotion is an operator decision; it does not certify the variant as a tested winner."},"promotedBy":{"type":"string","description":"Optional attribution for who/what triggered the promotion."}},"additionalProperties":true}}},"description":"The variant to promote for this component."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"componentId","required":true,"description":"Component identifier."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteMgmtProjectsByIdComponentsByComponentIdPromote","summary":"Remove the latest promotion for a component","tags":["mgmt"],"description":"Remove the latest promotion for a component. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"componentId","required":true,"description":"Component identifier."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/components/{componentId}/archive":{"post":{"operationId":"postMgmtProjectsByIdComponentsByComponentIdArchive","summary":"Hide a component that is no longer on the site","tags":["mgmt"],"description":"Hide a component that is no longer on the site. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"componentId","required":true,"description":"Component identifier."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/components/{componentId}/unarchive":{"post":{"operationId":"postMgmtProjectsByIdComponentsByComponentIdUnarchive","summary":"Restore an archived component","tags":["mgmt"],"description":"Restore an archived component. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"componentId","required":true,"description":"Component identifier."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/components/{cid}/migration-preview":{"get":{"operationId":"getMgmtProjectsByIdComponentsByCidMigrationPreview","summary":"Preview migrating a variants component onto one experiment with generated versions","tags":["mgmt"],"description":"Preview migrating a variants component onto one experiment with generated versions. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."},{"schema":{"type":"string"},"in":"path","name":"cid","required":true,"description":"Component id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/components/{cid}/migrate":{"post":{"operationId":"postMgmtProjectsByIdComponentsByCidMigrate","summary":"Freeze a variants experiment and carry its versions into one experiment","tags":["mgmt"],"description":"Freeze a variants experiment and carry its versions into one experiment. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."},{"schema":{"type":"string"},"in":"path","name":"cid","required":true,"description":"Component id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/goals":{"get":{"operationId":"getMgmtProjectsByIdGoals","summary":"Goal hit counts, per-variant completion rates, and revenue aggregates","tags":["mgmt"],"description":"Goal hit counts, per-variant completion rates, and revenue aggregates. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default 30d). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"goals":{"type":"array","items":{"type":"object","additionalProperties":true}},"currency":{"type":"string","description":"Project display currency (ISO-4217) for the revenue fields"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/analytics":{"get":{"operationId":"getMgmtProjectsByIdAnalytics","summary":"Daily first-exposure cohorts and window totals per variant","tags":["mgmt"],"description":"Daily first-exposure cohorts and window totals per variant. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default 30d). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"query","name":"component","required":false,"description":"Restrict to one component id"},{"schema":{"type":"string"},"in":"query","name":"device","required":false,"description":"Restrict to one device class (e.g. mobile, desktop)"},{"schema":{"type":"string"},"in":"query","name":"source","required":false,"description":"Restrict to one traffic source (direct, search, social, referral)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","description":"Daily series, one row per (day, component_id, variant_id): a first-exposure cohort. Each exposed human session counts ONCE, on the day (project timezone) of its first exposure to the variant in the window, in `visitors`; it is in `conversions` iff a goal on the variant came at or after that first exposure (the `totals` rule), even on a later day. So the rows sum exactly to `totals`. `cvr` = conversions ÷ visitors, null when visitors = 0. A day with no first exposure has NO row — a gap, never a 0% point. The last days are right-censored: their visitors have had less time to convert.","items":{"type":"object","properties":{"day":{"type":"string","description":"YYYY-MM-DD in the project reporting timezone"},"component_id":{"type":"string"},"variant_id":{"type":"string"},"visitors":{"type":"integer","description":"Human sessions whose first exposure in the window fell on this day"},"conversions":{"type":"integer","description":"Of those visitors, the ones with a goal on the variant at/after their first exposure"},"cvr":{"type":"number","nullable":true,"description":"conversions ÷ visitors; null when visitors = 0, never 0"},"impressions":{"type":"integer","description":"Deprecated alias of `visitors`"}},"additionalProperties":true}},"totals":{"type":"array","description":"Window totals per (component_id, variant_id), each counted ONCE over the whole window with the same filters as `data`: `visitors` = distinct human sessions exposed to the variant, `conversions` = those visitors with a goal on the variant at or after their first exposure in the window, `conversion_rate` = conversions ÷ visitors (null with no visitors). Unfiltered, these equal GET /components `exposed_sessions` / `conversions` for the same window.","items":{"type":"object","properties":{"component_id":{"type":"string"},"variant_id":{"type":"string"},"visitors":{"type":"integer"},"conversions":{"type":"integer"},"conversion_rate":{"type":"number","nullable":true}},"additionalProperties":true}}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/health":{"get":{"operationId":"getMgmtProjectsByIdHealth","summary":"Project ingestion health and windowed traffic breakdown","tags":["mgmt"],"description":"Project ingestion health and windowed traffic breakdown. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all'. Omit range/from/to entirely for the legacy rolling last-24-hours window. Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"events24h":{"type":"number"},"sessions24h":{"type":"number"},"agentCalls":{"type":"number"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/trends":{"get":{"operationId":"getMgmtProjectsByIdTrends","summary":"CVR momentum, session volume, and breakdown trends","tags":["mgmt"],"description":"CVR momentum, session volume, and breakdown trends. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default 7d). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"range":{"type":"string"},"cvr":{"type":"array","description":"One row per (componentId, variantId) — variant ids are unique only within a component, so key rows by both. variantId alone is kept for older clients but is ambiguous when two components share an arm id (e.g. `control`).","items":{"type":"object","additionalProperties":true}},"momentum":{"type":"array","description":"One row per (componentId, variantId), same keying as cvr.","items":{"type":"object","additionalProperties":true}},"componentSparklines":{"type":"array","description":"Conversion-rate history, one series per (componentId, variantId). Cohort by first exposure: each exposed human session counts once, in the bucket (window.bucketUnit: day/week/month) of its first exposure to that arm in the window, and converts iff a goal on that arm came at or after that exposure. points[]: { date, cvr, visitors, conversions }.","items":{"type":"object","additionalProperties":true}},"sparklines":{"type":"array","deprecated":true,"description":"Deprecated alias of componentSparklines (was pooled by variantId across components).","items":{"type":"object","additionalProperties":true}},"deviceBreakdown":{"type":"array","description":"One row per (componentId, variantId, device). impressions = exposed human sessions in the current period; currentCvr/priorCvr count a session as converted only if its goal on that arm came at/after its first exposure in that period.","items":{"type":"object","additionalProperties":true}},"sourceBreakdown":{"type":"array","description":"Top 5 traffic sources per (componentId, variantId) plus an `other` roll-up; same counting as deviceBreakdown.","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/guardrail-events":{"get":{"operationId":"getMgmtProjectsByIdGuardrailEvents","summary":"Variants currently paused — by a guardrail (source: guardrail) or by a teammate (source: manual); optionally only pauses within ?days","tags":["mgmt"],"description":"Variants currently paused — by a guardrail (source: guardrail) or by a teammate (source: manual); optionally only pauses within ?days. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":365},"in":"query","name":"days","required":false,"description":"Only pauses fired within the last N days. Omit for every still-paused variant."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"guardrailEvents":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/device-stats":{"get":{"operationId":"getMgmtProjectsByIdDeviceStats","summary":"Per-device visitors, conversions, and CVR per variant in a window","tags":["mgmt"],"description":"Per-device visitors, conversions, and CVR per variant in a window. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default 30d). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"query","name":"component","required":false,"description":"Restrict to one component id"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"devices":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"One row per (device, componentId, variantId) over the window (default 30d; `range=all` for lifetime). `visitors` = distinct human sessions EXPOSED to the variant in the window (not raw impression events); `conversions` = those visitors with a goal on the variant at or after their first exposure in the window; `cvr` = conversions ÷ visitors — counted the way GET /components counts `exposed_sessions` / `conversions`. `impressions` is a deprecated alias of `visitors`."}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/lift":{"get":{"operationId":"getMgmtProjectsByIdLift","summary":"Conversion lift of personalization vs. holdout","tags":["mgmt"],"description":"Conversion lift of personalization vs. holdout. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"liftPct":{"type":"number"},"significant":{"type":"boolean","description":"Always-valid at 95% (mSPRT): safe to read on every page load and act on the moment it turns true, unlike a fixed-horizon test."},"pValue":{"type":"number","nullable":true,"description":"Always-valid p-value; null while collecting."},"diffInterval":{"type":"object","nullable":true,"description":"Always-valid range on the absolute conversion-rate difference (treated − holdout), the mSPRT inverted at the same alpha. Excludes 0 exactly when `significant`. Null while collecting.","properties":{"lower":{"type":"number"},"upper":{"type":"number"}}},"epochs":{"type":"number","description":"Assignment epochs (distinct holdout rates) the number combines. 1 is a plain two-arm comparison; above 1 the lift is estimated within each epoch and combined, and the cvr figures are epoch-standardized rates."},"pinnedExcluded":{"type":"number"},"revenue":{"type":"object","nullable":true,"description":"Revenue-per-visit lift — null when the project has no valued conversions. Directional in v1 (no significance test).","properties":{"status":{"type":"string"},"revenuePerVisitTreated":{"type":"number"},"revenuePerVisitHoldout":{"type":"number"},"liftPct":{"type":"number","nullable":true}},"additionalProperties":true}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/verification":{"get":{"operationId":"getMgmtProjectsByIdVerification","summary":"Setup verification status, milestones, and observed surfaces","tags":["mgmt"],"description":"Install status and onboarding milestones (all-time), plus `seen`: the distinct components, versions and goals observed from the site in the last 30 days. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/verification/test-event":{"post":{"operationId":"postMgmtProjectsByIdVerificationTestEvent","summary":"Send a synthetic test event to verify ingestion without deploying","tags":["mgmt"],"description":"Send a synthetic test event to verify ingestion without deploying. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"sessionId":{"type":"string"}},"required":["ok","sessionId"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/graph/edges":{"get":{"operationId":"getMgmtProjectsByIdGraphEdges","summary":"List graph edges for a page","tags":["mgmt"],"description":"List graph edges for a page. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Edges keyed under `edges`","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Edges keyed under `edges`"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/graph/node-clusters":{"get":{"operationId":"getMgmtProjectsByIdGraphNodeClusters","summary":"Dominant audience cluster per component","tags":["mgmt"],"description":"The audience cluster with the most exposures to each component over the last 30 days (reliable portraits, human sessions). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Clusters keyed under `clusters`","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Clusters keyed under `clusters`"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/graph/component-pages":{"get":{"operationId":"getMgmtProjectsByIdGraphComponentPages","summary":"Page path each component was last seen on","tags":["mgmt"],"description":"Page path each component was last seen on. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Assignments keyed under `assignments`","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Assignments keyed under `assignments`"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/layout-stats":{"get":{"operationId":"getMgmtProjectsByIdLayoutStats","summary":"Per-persona layout weights","tags":["mgmt"],"description":"Per-persona layout weights. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Layout stats rows","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Layout stats rows"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/shadow-stats":{"get":{"operationId":"getMgmtProjectsByIdShadowStats","summary":"Shadow-mode decision stats","tags":["mgmt"],"description":"Shadow-mode decision stats. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Shadow decision summary","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"shadowDecisions":{"type":"number"},"personaCount":{"type":"number"},"readyToPromote":{"type":"boolean"},"minRequired":{"type":"number"}},"additionalProperties":true,"description":"Shadow decision summary"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/graph":{"get":{"operationId":"getMgmtProjectsByIdGraph","summary":"Component graph for a project or page","tags":["mgmt"],"description":"Component graph for a project or page. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Page summary (`pages`) or page nodes (`nodes`)","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Page summary (`pages`) or page nodes (`nodes`)"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/portraits":{"get":{"operationId":"getMgmtProjectsByIdPortraits","summary":"Persona clusters for a project","tags":["mgmt"],"description":"Persona clusters for a project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Session totals and per-cluster persona dimensions","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"totalSessions":{"type":"integer"},"reliableSessions":{"type":"integer"},"avgReliability":{"type":"number","nullable":true},"clusters":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true,"description":"Session totals and per-cluster persona dimensions"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/portraits/trend":{"get":{"operationId":"getMgmtProjectsByIdPortraitsTrend","summary":"Audience active-mix trend for a project","tags":["mgmt"],"description":"Audience active-mix trend for a project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default 7d). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Continuous bucket axis and one point series per audience","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"buckets":{"type":"array","items":{"type":"string"}},"series":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"points":{"type":"array","items":{"type":"integer"}}},"additionalProperties":true}}},"additionalProperties":true,"description":"Continuous bucket axis and one point series per audience"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/engagement-matrix":{"get":{"operationId":"getMgmtProjectsByIdEngagementMatrix","summary":"Persona × section engagement matrix","tags":["mgmt"],"description":"Persona × section engagement matrix. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Persona × section attention indices with confidence intervals","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"window":{"type":"string"},"sections":{"type":"array","items":{"type":"string"}}},"additionalProperties":true,"description":"Persona × section attention indices with confidence intervals"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/engagement-signals":{"get":{"operationId":"getMgmtProjectsByIdEngagementSignals","summary":"Engagement signal counts per component/variant","tags":["mgmt"],"description":"Engagement signal counts per component/variant. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default 7d). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Behavioural engagement signal counts with exposure denominators","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"components":{"type":"array","items":{"type":"object","properties":{"component_id":{"type":"string"},"exposed_sessions":{"type":"integer"},"variants":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}},"additionalProperties":true,"description":"Behavioural engagement signal counts with exposure denominators"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/webhooks":{"get":{"operationId":"getMgmtProjectsByIdWebhooks","summary":"List project webhooks","tags":["mgmt"],"description":"List project webhooks. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"label":{"type":"string","nullable":true},"url":{"type":"string"},"active":{"type":"boolean"}},"additionalProperties":true}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"postMgmtProjectsByIdWebhooks","summary":"Create a webhook","tags":["mgmt"],"description":"Create a webhook. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type","url"],"description":"The webhook to create.","properties":{"type":{"type":"string","enum":["generic","slack"],"description":"Delivery type. 'generic' HMAC-signs deliveries and returns a signing secret once; 'slack' posts to a Slack incoming-webhook URL."},"url":{"type":"string","description":"Endpoint the webhook POSTs to. Must be a valid absolute URL."},"label":{"type":"string","description":"Optional human-readable label."}},"additionalProperties":true}}},"description":"The webhook to create."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"201":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"secret":{"type":"string","nullable":true}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/webhooks/{webhookId}/test":{"post":{"operationId":"postMgmtProjectsByIdWebhooksByWebhookIdTest","summary":"Test a webhook","tags":["mgmt"],"description":"Test a webhook. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"webhookId","required":true,"description":"Webhook UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"error":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"error":{"type":"string"}},"additionalProperties":true}}}}}}},"/v1/mgmt/projects/{id}/webhooks/{webhookId}":{"delete":{"operationId":"deleteMgmtProjectsByIdWebhooksByWebhookId","summary":"Delete a webhook","tags":["mgmt"],"description":"Delete a webhook. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"webhookId","required":true,"description":"Webhook UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/billing":{"get":{"operationId":"getMgmtBilling","summary":"Get billing summary","tags":["mgmt"],"description":"Get billing summary. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Billing summary","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string","description":"Current plan id"},"sessionsUsed":{"type":"number","description":"Sessions counted this month"},"likelyAutomatedSessions":{"type":"number","description":"Of sessionsUsed, how many the bot scorer has since rated at or over its bar. Metering happens at admission on the automation flag alone, so these were counted; the Home page's \"human visitors\" excludes them, and this is the gap between the two numbers."},"sessionsLimit":{"type":"number","description":"Monthly session allowance for the plan"},"sessionsPct":{"type":"number","description":"sessionsUsed / sessionsLimit"},"projectCount":{"type":"number","description":"Number of projects on the account"},"stripeCustomerId":{"type":"string","nullable":true,"description":"Stripe customer id, if any"},"billingSource":{"type":"string","description":"Which rail owns the plan: 'stripe' or 'shopify' (Managed Pricing via the Shopify app)"},"shopifyShop":{"type":"string","nullable":true,"description":"myshopify domain whose Shopify plan page changes this plan"},"contractEndsAt":{"type":"string","nullable":true,"description":"When an admin-assigned (contract) plan ends; the account moves to Free then. Null for self-serve plans."},"limits":{"type":"object","description":"Plan entitlement caps; null means unlimited","properties":{"seats":{"type":"number","nullable":true},"projects":{"type":"number","nullable":true},"componentsPerProject":{"type":"number","nullable":true},"liveGoals":{"type":"number","nullable":true},"chatPerDay":{"type":"number"},"maxRetentionDays":{"type":"number"}},"additionalProperties":true}},"additionalProperties":true,"description":"Billing summary"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/billing/usage-status":{"get":{"operationId":"getMgmtBillingUsageStatus","summary":"Get the account visitor-limit status","tags":["mgmt"],"description":"Get the account visitor-limit status. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"state":{"type":"string","enum":["ok","approaching","over"]},"plan":{"type":"string"},"sessionsUsed":{"type":"number"},"sessionsLimit":{"type":"number","nullable":true},"canManageBilling":{"type":"boolean"},"billingSource":{"type":"string","enum":["stripe","shopify"],"description":"Which rail owns the plan — readable by every member, since /billing is admin-only"}},"additionalProperties":true}}}}}}},"/v1/mgmt/billing/checkout":{"post":{"operationId":"postMgmtBillingCheckout","summary":"Create a Stripe checkout session","tags":["mgmt"],"description":"Starts a Stripe Checkout session for a plan upgrade. Supports the Idempotency-Key header: a retried request with the same key returns the original checkout URL instead of creating a duplicate session. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string","description":"Target plan id (starter, growth, scale)"},"billing":{"type":"string","enum":["monthly","annual"],"description":"Billing cycle; defaults to monthly"}}}}}},"parameters":[{"schema":{"type":"string","maxLength":255},"in":"header","name":"Idempotency-Key","required":false,"description":"Client-supplied key; a retried POST with the same key replays the first response."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Checkout session created","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Stripe Checkout URL to redirect the user to"},"portal":{"type":"boolean","description":"True when the URL is a billing-portal session (the customer already has a live subscription and must swap/manage there rather than start a duplicate checkout)."}},"additionalProperties":true,"description":"Checkout session created"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/billing/portal":{"post":{"operationId":"postMgmtBillingPortal","summary":"Create a Stripe billing portal session","tags":["mgmt"],"description":"Create a Stripe billing portal session. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Billing portal session created","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Stripe billing portal URL"}},"additionalProperties":true,"description":"Billing portal session created"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/stream":{"get":{"operationId":"getMgmtProjectsByIdStream","summary":"Live project snapshot (Server-Sent Events)","tags":["mgmt"],"description":"Streams a rolling snapshot of the project as `text/event-stream`, NOT JSON. Each message is an array of component rows with the same fields and numbers as `GET /projects/:id/components` for the same window (evidence and baseline included), Archived components are omitted unless `includeArchived=1` (then flagged `archived: true`). Counts are rebuilt at most every ~12s (up to ~60s on projects whose snapshot is slow to build); across API machines one of them builds and the others serve its published snapshot, so a delivered snapshot is normally about one interval behind the data; a machine that cannot get a fresher one rebuilds itself once its own is two intervals old, so the worst case is ~3 intervals (~3 min on the slowest projects). Evidence (`evidence_state`, `evidence_stats`, `window_evidence`) is rebuilt at most every ~60s and on every window roll-over, so between rebuilds it may lag the counts. The connection stays open until the client disconnects; a snapshot is sent only when it changed, and an SSE comment (`: ping`) keeps an idle connection open every ~25s. Access is re-checked every ~60s (a revoked sk_ or a removed team member stops receiving) and every connection is closed after ~10 minutes (and when the API machine shuts down, `reason: shutdown`); all send `event: end` with a `reason` first, and a client simply reconnects. At most 6 open streams per user and 20 per project per API machine; beyond that the request is a `429 too_many_streams`. A `to` after today is treated as \"through today\" (the same window as no `to`). Use `?range=7d|30d|all` to window the counts. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token for a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default all). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"query","name":"includeArchived","required":false,"description":"Set to '1'/'true' to include archived components (each flagged `archived: true`). Omitted by default, as on GET /components."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/mgmt/shopify/connect":{"post":{"operationId":"postMgmtShopifyConnect","summary":"Connect a Shopify store without pasting keys","tags":["mgmt"],"description":"Connect a Shopify store without pasting keys. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","state"],"properties":{"projectId":{"type":"string"},"state":{"type":"string","maxLength":2048}},"additionalProperties":false}}}},"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"shop":{"type":"string"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/shopify-connections":{"get":{"operationId":"getMgmtProjectsByIdShopifyConnections","summary":"Shopify stores connected to this project","tags":["mgmt"],"description":"Shopify stores connected to this project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Pass to disconnect: the newest connect pair (its sk_ key id), or the shop domain for a store connected with pasted keys."},"shop":{"type":"string"},"createdAt":{"type":"string"},"pkPrefix":{"type":"string","nullable":true},"skPrefix":{"type":"string","nullable":true},"keyPairs":{"type":"integer","description":"Live connect pairs for this store; Disconnect revokes all of them."},"via":{"type":"string","enum":["connect","pasted"]},"connected":{"type":"boolean","description":"The store is live on this project (false: a connect awaiting confirmation in the Shopify admin, or a store that moved away)."},"movedAway":{"type":"boolean","description":"The store has since connected to another project; its old pair here is left over."}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/shopify-connections/{keyId}":{"delete":{"operationId":"deleteMgmtProjectsByIdShopifyConnectionsByKeyId","summary":"Disconnect a Shopify store (revokes its connect key pairs)","tags":["mgmt"],"description":"Disconnect a Shopify store (revokes its connect key pairs). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."},{"schema":{"type":"string"},"in":"path","name":"keyId","required":true,"description":"Key id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/export":{"get":{"operationId":"getMgmtProjectsByIdExport","summary":"Export project data bundle","tags":["mgmt"],"description":"Export project data bundle. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Aggregate project export (excludes raw_events). `events.total` counts at most 1,000,000 events; `events.totalCapped` is true when there are more (page /export/events for the full set).","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"exportedAt":{"type":"string","description":"ISO 8601 export timestamp"},"portraitsNextCursor":{"type":"string","nullable":true,"description":"The bundle carries the first 5000 portraits; pass this to /export/portraits for the rest. Null when all are included."},"note":{"type":"string"}},"additionalProperties":true,"description":"Aggregate project export (excludes raw_events). `events.total` counts at most 1,000,000 events; `events.totalCapped` is true when there are more (page /export/events for the full set)."}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/export/events":{"get":{"operationId":"getMgmtProjectsByIdExportEvents","summary":"Export raw events (keyset paginated)","tags":["mgmt"],"description":"Ordered by the server insert time (ingested_at, id), not the SDK event `timestamp` (an offline batch arrives with old timestamps), so `resumeCursor` is a safe incremental-sync point. Rows ingested in the last minute are served on a later call. A legacy `<timestamp>|<id>` cursor still pages the old event-time order. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"A page of raw events","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"nextCursor":{"type":"string","nullable":true,"description":"Pass back to fetch the next page; null when exhausted"},"count":{"type":"integer","description":"Number of events in this page"},"resumeCursor":{"type":"string","nullable":true,"description":"Store this for incremental sync: passing it later returns only rows ingested after this page. Present even on the last page (where nextCursor is null); null only when nothing has been exported yet. Rows ingested in the last 60 seconds are not served yet (they may still be committing)."}},"additionalProperties":true,"description":"A page of raw events"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/export/decisions":{"get":{"operationId":"getMgmtProjectsByIdExportDecisions","summary":"Export slot decisions with their provenance (keyset paginated)","tags":["mgmt"],"description":"The off-policy dataset (migrations 146/157): one row per slot decision with the arm served, the candidate arm space, the logged propensity, the policy rung that decided (`policy_kind`), the context the policy read, the serving version, and the reward close-out credited (net of any refund clawed back since). NULL propensity rows were decided before 146, by a deterministic rung, or by the factored model — exclude them from any estimator rather than impute. **Snapshot export, not an incremental feed.** `closed_at` and `credited_reward` are written by close-out after the decision, and a re-decide moves `decided_at` forward, so a sync that resumes from an old cursor never sees credit that landed on rows it already read. Re-export the window you need (or join `/export/goal-events`, which is incremental-safe) instead of storing a cursor. Decisions made in the last minute (or during a still-open transaction) are served on a later call. Ordered by (decided_at, session_id, slot_id). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"nextCursor":{"type":"string","nullable":true,"description":"Pass back to fetch the next page; null when exhausted"},"count":{"type":"integer","description":"Number of decisions in this page"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/export/layout-decisions":{"get":{"operationId":"getMgmtProjectsByIdExportLayoutDecisions","summary":"Export layout decisions with their provenance (keyset paginated)","tags":["mgmt"],"description":"One row per session that received a layout decision: the served order, the candidate layout hashes, the logged propensity and policy rung (migration 157), whether the feasibility gate held it, and the context read, and the reward ledger (migration 162): `credited_reward` is the credit summed over the draw’s closed trials (one per visit that rendered sections) and `credited_trials` their count, so the per-trial reward is their ratio. Null / 0 until a trial closes; rows whose trials closed before 162 carry no ledger — join `goal_events` by session for those. **Snapshot export, not an incremental feed.** `credited_reward` and `credited_trials` are written by close-out after the decision, and a re-decide moves `decided_at` forward, so a sync that resumes from an old cursor never sees credit that landed on rows it already read. Re-export the window you need (or join `/export/goal-events`, which is incremental-safe) instead of storing a cursor. Decisions made in the last minute (or during a still-open transaction) are served on a later call. Ordered by (decided_at, session_id). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"nextCursor":{"type":"string","nullable":true,"description":"Pass back to fetch the next page; null when exhausted"},"count":{"type":"integer","description":"Number of decisions in this page"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/export/portraits":{"get":{"operationId":"getMgmtProjectsByIdExportPortraits","summary":"Export visitor portraits (keyset paginated)","tags":["mgmt"],"description":"One behavioural portrait per session (the seven traits, cluster, reliability), ordered by session_id. The bundle at /export carries the first page and its `portraitsNextCursor`. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"nextCursor":{"type":"string","nullable":true,"description":"Pass back to fetch the next page; null when exhausted"},"count":{"type":"integer","description":"Number of portraits in this page"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/export/goal-events":{"get":{"operationId":"getMgmtProjectsByIdExportGoalEvents","summary":"Export goal events (keyset paginated)","tags":["mgmt"],"description":"Server-recorded conversions and refunds (`kind`) with value and currency, ordered by the server insert time (ingested_at, id) — not created_at, which is the order's own occurredAt and can be back-dated — so `resumeCursor` is a safe incremental-sync point. Rows ingested in the last minute are served on a later call. The `raw_events goal_achieved` path is exported separately at /export/events. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"nextCursor":{"type":"string","nullable":true,"description":"Pass back to fetch the next page; null when exhausted"},"count":{"type":"integer","description":"Number of goalEvents in this page"},"resumeCursor":{"type":"string","nullable":true,"description":"Store this for incremental sync: passing it later returns only rows ingested after this page. Present even on the last page (where nextCursor is null); null only when nothing has been exported yet. Rows ingested in the last 60 seconds are not served yet (they may still be committing)."}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/export/weights":{"get":{"operationId":"getMgmtProjectsByIdExportWeights","summary":"Export the learned weight tables","tags":["mgmt"],"description":"The posteriors serving reads: slot_weights (per arm × segment × persona cell, with the value posterior), layout_weights (per layout hash × persona) and layout_factor_weights. A snapshot as of now — these move on every close-out pass, which is why decisions log their own propensity. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"exportedAt":{"type":"string"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/audit":{"get":{"operationId":"getMgmtProjectsByIdAudit","summary":"List audit entries","tags":["mgmt"],"description":"List audit entries. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Page of audit entries","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Audit event UUID"},"user_id":{"type":"string"},"actor_email":{"type":"string","nullable":true,"description":"The actor's email, resolved from user_id"},"project_id":{"type":"string","nullable":true},"action":{"type":"string"},"ip":{"type":"string","nullable":true}},"additionalProperties":true}},"nextCursor":{"type":"string","nullable":true,"description":"Keyset cursor for the next page"}},"additionalProperties":true,"description":"Page of audit entries"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/audit/export":{"get":{"operationId":"getMgmtProjectsByIdAuditExport","summary":"Export the audit trail as CSV","tags":["mgmt"],"description":"Downloads the filtered audit trail as `text/csv`, NOT JSON, with a `Content-Disposition: attachment` filename. Same visibility gate and `action` / `from` / `to` filters as `GET /projects/{id}/audit`, but bounded rather than paginated — at most 10000 rows, newest first. Columns: created_at, user_id, action, ip, metadata. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"action","required":false,"description":"Only rows with this audit action."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"ISO-8601 lower bound on created_at (inclusive)."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"ISO-8601 upper bound on created_at (inclusive)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/audit/actions":{"get":{"operationId":"getMgmtProjectsByIdAuditActions","summary":"List distinct audit actions","tags":["mgmt"],"description":"List distinct audit actions. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Distinct action names seen for this project","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"actions":{"type":"array","items":{"type":"string"}}},"additionalProperties":true,"description":"Distinct action names seen for this project"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/feedback":{"get":{"operationId":"getMgmtAdminFeedback","summary":"Admin: user feedback feed (cursor-paginated)","tags":["mgmt"],"description":"Admin: user feedback feed (cursor-paginated). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":true}},"nextCursor":{"type":"string","nullable":true,"description":"Pass as `?cursor=` for the next page; null on the last page."}},"additionalProperties":true}}}}}}},"/v1/mgmt/admin/contracts/expiring":{"get":{"operationId":"getMgmtAdminContractsExpiring","summary":"Admin: contract accounts expiring soon or recently lapsed","tags":["mgmt"],"description":"Admin: contract accounts expiring soon or recently lapsed. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/projects":{"get":{"operationId":"getMgmtAdminProjects","summary":"List all projects across tenants","tags":["mgmt"],"description":"List all projects across tenants. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"sentryConfigured":{"type":"boolean"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/projects/{id}/plan":{"post":{"operationId":"postMgmtAdminProjectsByIdPlan","summary":"Set a project owner's plan","tags":["mgmt"],"description":"Set a project owner's plan. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plan"],"description":"Plan change for the project's owner. `plan` is required. When a paid plan is chosen, `compExpiresAt` is required and must be in the future; when 'free' is chosen, any comp expiry is cleared.","properties":{"plan":{"type":"string","description":"Billing plan — one of 'free', 'starter', 'growth', 'scale', 'agency', 'enterprise'."},"compExpiresAt":{"type":"string","nullable":true,"description":"ISO-8601 timestamp when a complimentary paid plan expires. Required (and must be in the future) for any paid plan; ignored for the free plan."}},"additionalProperties":true}}},"description":"Plan change for the project's owner. `plan` is required. When a paid plan is chosen, `compExpiresAt` is required and must be in the future; when 'free' is chosen, any comp expiry is cleared."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"plan":{"type":"string"},"comp_expires_at":{"type":"string","nullable":true}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/projects/{id}":{"get":{"operationId":"getMgmtAdminProjectsById","summary":"Get full admin view of a project","tags":["mgmt"],"description":"Get full admin view of a project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteMgmtAdminProjectsById","summary":"Hard-delete any project","tags":["mgmt"],"description":"Hard-delete any project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/projects/{id}/disabled":{"post":{"operationId":"postMgmtAdminProjectsByIdDisabled","summary":"Toggle a project ingest kill switch","tags":["mgmt"],"description":"Toggle a project ingest kill switch. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Ingest kill switch. Only `disabled: true` disables the project; any other value (or an omitted field) re-enables it.","properties":{"disabled":{"type":"boolean","description":"When true, blocks all event ingest for the project."}},"additionalProperties":true}}},"description":"Ingest kill switch. Only `disabled: true` disables the project; any other value (or an omitted field) re-enables it."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"disabled":{"type":"boolean"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/projects/{id}/reseed-demo":{"post":{"operationId":"postMgmtAdminProjectsByIdReseedDemo","summary":"Seed or re-seed a project with the Formly demo fixture (admin)","tags":["mgmt"],"description":"Seed or re-seed a project with the Formly demo fixture (admin). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID (demo, or empty of sessions)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"projectId":{"type":"string"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/projects/{id}/keys/{keyId}/revoke":{"post":{"operationId":"postMgmtAdminProjectsByIdKeysByKeyIdRevoke","summary":"Revoke an API key on any project (admin)","tags":["mgmt"],"description":"Revoke an API key on any project (admin). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"keyId","required":true,"description":"API key id to revoke."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/impersonate":{"post":{"operationId":"postMgmtAdminImpersonate","summary":"Begin read-only view-as for a project (admin)","tags":["mgmt"],"description":"Begin read-only view-as for a project (admin). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId"],"properties":{"projectId":{"type":"string","description":"Project to view as (read-only)."}},"additionalProperties":true}}}},"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"projectId":{"type":"string"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/impersonate/stop":{"post":{"operationId":"postMgmtAdminImpersonateStop","summary":"End a view-as session (admin)","tags":["mgmt"],"description":"End a view-as session (admin). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}}}}},"/v1/mgmt/admin/users/{id}":{"delete":{"operationId":"deleteMgmtAdminUsersById","summary":"Hard-delete a user and everything they own","tags":["mgmt"],"description":"Hard-delete a user and everything they own. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"User account ID (Clerk user id)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"deletedProjects":{"type":"number"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"getMgmtAdminUsersById","summary":"Get full admin view of a user","tags":["mgmt"],"description":"Get full admin view of a user. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"User account ID (Clerk user id)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/audit":{"get":{"operationId":"getMgmtAdminAudit","summary":"Global audit feed","tags":["mgmt"],"description":"Global audit feed. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"nextCursor":{"type":"string","nullable":true}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/whoami":{"get":{"operationId":"getMgmtAdminWhoami","summary":"Check the caller is an admin","tags":["mgmt"],"description":"Check the caller is an admin. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"admin":{"type":"boolean"},"userId":{"type":"string"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/users":{"get":{"operationId":"getMgmtAdminUsers","summary":"List all user accounts","tags":["mgmt"],"description":"List all user accounts. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/users/{id}/plan":{"post":{"operationId":"postMgmtAdminUsersByIdPlan","summary":"Set a user's plan","tags":["mgmt"],"description":"Set a user's plan. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plan"],"description":"Plan change applied directly to the user account. `plan` is required. When a paid plan is chosen, `compExpiresAt` is required and must be in the future; when 'free' is chosen, any comp expiry is cleared.","properties":{"plan":{"type":"string","description":"Billing plan — one of 'free', 'starter', 'growth', 'scale', 'agency', 'enterprise'."},"compExpiresAt":{"type":"string","nullable":true,"description":"ISO-8601 timestamp when a complimentary paid plan expires. Required (and must be in the future) for any paid plan; ignored for the free plan."}},"additionalProperties":true}}},"description":"Plan change applied directly to the user account. `plan` is required. When a paid plan is chosen, `compExpiresAt` is required and must be in the future; when 'free' is chosen, any comp expiry is cleared."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"User account ID (Clerk user id)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"plan":{"type":"string"},"comp_expires_at":{"type":"string","nullable":true}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/users/{id}/staff-access":{"get":{"operationId":"getMgmtAdminUsersByIdStaffAccess","summary":"Admin: partner-manager grants on and held by a user","tags":["mgmt"],"description":"Admin: partner-manager grants on and held by a user. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"User account ID (Clerk user id)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"operationId":"putMgmtAdminUsersByIdStaffAccess","summary":"Admin: grant a partner manager access to this account","tags":["mgmt"],"description":"Admin: grant a partner manager access to this account. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"User account ID (Clerk user id)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/admin/users/{id}/staff-access/{granteeId}":{"delete":{"operationId":"deleteMgmtAdminUsersByIdStaffAccessByGranteeId","summary":"Admin: revoke a partner manager's access to this account","tags":["mgmt"],"description":"Admin: revoke a partner manager's access to this account. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Account owner Clerk user id."},{"schema":{"type":"string"},"in":"path","name":"granteeId","required":true,"description":"Partner manager Clerk user id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/notifications":{"get":{"operationId":"getMgmtNotifications","summary":"List notifications","tags":["mgmt"],"description":"List notifications. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"unread","required":false,"description":"'true' to return only unread notifications."},{"schema":{"type":"string"},"in":"query","name":"project_id","required":false,"description":"Filter to a single project UUID."},{"schema":{"type":"string"},"in":"query","name":"type","required":false,"description":"Filter to a single notification type."},{"schema":{"type":"string"},"in":"query","name":"limit","required":false,"description":"Max notifications per page (1–100, default 25)."},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Keyset cursor (\"<createdAtISO>|<id>\") from a prior page's nextCursor. Preferred over before."},{"schema":{"type":"string","deprecated":true},"in":"query","name":"before","required":false,"description":"Deprecated: return notifications created before this timestamp. Use cursor instead."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Notifications for the caller, newest first","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"notifications":{"type":"array","items":{"type":"object","additionalProperties":true}},"nextCursor":{"type":"string","nullable":true,"description":"Keyset cursor for the next page, or null on the last page."}},"additionalProperties":true,"description":"Notifications for the caller, newest first"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/notifications/unread-count":{"get":{"operationId":"getMgmtNotificationsUnreadCount","summary":"Count unread notifications","tags":["mgmt"],"description":"Exact up to 99; past that `count` is 99 and `capped` is true. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"number","description":"Unread notifications, at most 99."},"capped":{"type":"boolean","description":"True when there are more than 99."}},"additionalProperties":true}}}}}}},"/v1/mgmt/notifications/read":{"post":{"operationId":"postMgmtNotificationsRead","summary":"Mark notifications read","tags":["mgmt"],"description":"Mark notifications read. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Notification ids to mark read. An empty or missing list is a no-op (updated: 0).","properties":{"ids":{"type":"array","items":{"type":"string","description":"Notification UUID."},"description":"Notification UUIDs to mark read. Only the caller's own unread rows are affected."}},"additionalProperties":true}}},"description":"Notification ids to mark read. An empty or missing list is a no-op (updated: 0)."},"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"updated":{"type":"number"}},"additionalProperties":true}}}}}}},"/v1/mgmt/notifications/read-all":{"post":{"operationId":"postMgmtNotificationsReadAll","summary":"Mark all notifications read","tags":["mgmt"],"description":"Mark all notifications read. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"updated":{"type":"number"}},"additionalProperties":true}}}}}}},"/v1/mgmt/notification-preferences":{"get":{"operationId":"getMgmtNotificationPreferences","summary":"Get notification preferences","tags":["mgmt"],"description":"Get notification preferences. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Per-type notification preferences","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"preferences":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true,"description":"Per-type notification preferences"}}}}}},"put":{"operationId":"putMgmtNotificationPreferences","summary":"Update notification preferences","tags":["mgmt"],"description":"Update notification preferences. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Per-type notification preferences to upsert. An empty or missing list is a no-op; entries with an unrecognized `type` are ignored.","properties":{"preferences":{"type":"array","description":"One entry per notification type to set.","items":{"type":"object","required":["type","in_app_enabled","email_enabled","webhook_enabled"],"properties":{"type":{"type":"string","enum":["ai_insight","guardrail_paused","shadow_ready","trend_threshold","health_degraded","plan_limit","milestone"],"description":"Notification type key."},"in_app_enabled":{"type":"boolean","description":"Show this type in the in-app bell."},"email_enabled":{"type":"boolean","description":"Send this type by email."},"email_address":{"type":"string","nullable":true,"description":"Override recipient address for this type; null uses the account default."},"webhook_enabled":{"type":"boolean","description":"Deliver this type to the configured webhook."}},"additionalProperties":true}}},"additionalProperties":true}}},"description":"Per-type notification preferences to upsert. An empty or missing list is a no-op; entries with an unrecognized `type` are ignored."},"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}}}}},"/v1/mgmt/notification-project-mutes":{"get":{"operationId":"getMgmtNotificationProjectMutes","summary":"List the projects whose notifications the caller has muted","tags":["mgmt"],"description":"List the projects whose notifications the caller has muted. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"mutedProjectIds":{"type":"array","items":{"type":"string"}}},"additionalProperties":true}}}}}}},"/v1/mgmt/notification-project-mutes/{projectId}":{"put":{"operationId":"putMgmtNotificationProjectMutesByProjectId","summary":"Mute or unmute a project's notifications for the caller","tags":["mgmt"],"description":"Mute or unmute a project's notifications for the caller. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"muted":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/insights":{"get":{"operationId":"getMgmtProjectsByIdInsights","summary":"Latest AI insights for a project","tags":["mgmt"],"description":"Latest AI insights for a project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Insights payload; status=empty when none generated yet","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["ok","empty"]},"narratorBullets":{"type":"array","items":{"type":"string"}},"advisorBullets":{"type":"array","items":{"type":"string"}},"generatedAt":{"type":"string","description":"ISO timestamp of generation"},"isStale":{"type":"boolean"}},"additionalProperties":true,"description":"Insights payload; status=empty when none generated yet"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/insights/refresh":{"post":{"operationId":"postMgmtProjectsByIdInsightsRefresh","summary":"Trigger AI insight generation (async)","tags":["mgmt"],"description":"Starts insight generation and returns 202 immediately. Poll the pollUrl (also in the Location header) — GET /v1/mgmt/projects/{id}/insights — for the generated result. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID"}],"security":[{"secretKey":[]}],"responses":{"202":{"description":"Generation started; poll pollUrl (also in the Location header)","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["status","jobId","pollUrl"],"properties":{"status":{"type":"string","enum":["generating"]},"jobId":{"type":"string","description":"Identifier for this generation run"},"pollUrl":{"type":"string","description":"GET this to poll for the generated insights"}},"description":"Generation started; poll pollUrl (also in the Location header)"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/discovered-goals":{"get":{"operationId":"getMgmtProjectsByIdDiscoveredGoals","summary":"List discovered goals","tags":["mgmt"],"description":"List discovered goals. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Undismissed discovered goals","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"signal_type":{"type":"string"},"component_id":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"session_count":{"type":"integer"},"confirmed":{"type":"boolean"}},"additionalProperties":true},"description":"Undismissed discovered goals"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/discovered-goals/{goalId}/confirm":{"post":{"operationId":"postMgmtProjectsByIdDiscoveredGoalsByGoalIdConfirm","summary":"Confirm a discovered goal","tags":["mgmt"],"description":"Confirm a discovered goal. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"goalId","required":true,"description":"Discovered-goal UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/discovered-goals/{goalId}/dismiss":{"post":{"operationId":"postMgmtProjectsByIdDiscoveredGoalsByGoalIdDismiss","summary":"Dismiss a discovered goal","tags":["mgmt"],"description":"Dismiss a discovered goal. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"goalId","required":true,"description":"Discovered-goal UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/observation-mode":{"patch":{"operationId":"patchMgmtProjectsByIdObservationMode","summary":"Toggle observation mode","tags":["mgmt"],"description":"Toggle observation mode. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enabled"],"description":"New observation-mode state.","properties":{"enabled":{"type":"boolean","description":"True to enter observation mode (the optimizer observes traffic but does not alter the UI); false to resume adapting."}},"additionalProperties":true}}},"description":"New observation-mode state."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"New observation-mode state","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"observationMode":{"type":"boolean"}},"additionalProperties":true,"description":"New observation-mode state"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/chat/sessions":{"get":{"operationId":"getMgmtProjectsByIdChatSessions","summary":"List chat sessions for a project","tags":["mgmt"],"description":"List chat sessions for a project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID"}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"sessions":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}}}}}},"/v1/mgmt/projects/{id}/chat":{"post":{"operationId":"postMgmtProjectsByIdChat","summary":"Talk to the project assistant (streaming, tool-using)","tags":["mgmt"],"description":"Streams a single assistant turn as `text/event-stream`, NOT JSON. Frames arrive as `{session}`, `{delta}`, `{tool_status}`, `{choice_prompt}`, `{artifact}` (proposal cards), then a final `[DONE]`. History is server-side: pass `sessionId` to continue a conversation, omit it to start one. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"One user turn. History is server-side: pass sessionId to continue a conversation, omit it to start one. choiceReply marks a tap on a chip the assistant offered (unmetered, capped per session). surface scopes a new session (ask | goal_builder | slot_wizard); a continued session keeps its stored surface. SSE frames: {session}, {delta}, {tool_status}, {choice_prompt}, {artifact} (proposal cards), then [DONE].","properties":{"sessionId":{"type":"string","description":"Existing chat session to continue"},"message":{"type":"string","description":"The user turn text"},"surface":{"type":"string","description":"Chat surface for a NEW session: ask (default), goal_builder, or slot_wizard"},"choiceReply":{"type":"object","description":"Present when the turn is a tap on an offered chip","properties":{"optionId":{"type":"string"},"label":{"type":"string"}}}},"additionalProperties":true}}},"description":"One user turn. History is server-side: pass sessionId to continue a conversation, omit it to start one. choiceReply marks a tap on a chip the assistant offered (unmetered, capped per session). surface scopes a new session (ask | goal_builder | slot_wizard); a continued session keeps its stored surface. SSE frames: {session}, {delta}, {tool_status}, {choice_prompt}, {artifact} (proposal cards), then [DONE]."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID"}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/mgmt/account/chat/sessions":{"get":{"operationId":"getMgmtAccountChatSessions","summary":"List account-scoped chat sessions","tags":["mgmt"],"description":"List account-scoped chat sessions. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"sessions":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}}}}}},"/v1/mgmt/chat/sessions/{sessionId}/messages":{"get":{"operationId":"getMgmtChatSessionsBySessionIdMessages","summary":"Messages of one chat session (owner only)","tags":["mgmt"],"description":"Messages of one chat session (owner only). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"sessionId","required":true,"description":"Session id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"summary":{"type":"string","nullable":true,"description":"Assistant-written summary of the session, or null before one exists."},"messages":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}}}}}},"/v1/mgmt/account/chat":{"post":{"operationId":"postMgmtAccountChat","summary":"Talk to the account assistant (streaming, tool-using)","tags":["mgmt"],"description":"Streams a single assistant turn as `text/event-stream`, NOT JSON, against the account-scoped assistant (no project context). Same frame contract as the project chat: `{session}`, `{delta}`, `{tool_status}`, `{choice_prompt}`, then `[DONE]`. Requires an account-scoped credential — a project-scoped key is rejected. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"One user turn against the account-scoped assistant (no project context). Same SSE contract as the project chat: {session}, {delta}, {tool_status}, {choice_prompt}, [DONE].","properties":{"sessionId":{"type":"string"},"message":{"type":"string"},"choiceReply":{"type":"object","properties":{"optionId":{"type":"string"},"label":{"type":"string"}}}},"additionalProperties":true}}},"description":"One user turn against the account-scoped assistant (no project context). Same SSE contract as the project chat: {session}, {delta}, {tool_status}, {choice_prompt}, [DONE]."},"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/mgmt/projects/{id}/clusters":{"get":{"operationId":"getMgmtProjectsByIdClusters","summary":"List project clusters","tags":["mgmt"],"description":"List project clusters. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Clusters ordered by member count","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Cluster UUID"},"label":{"type":"string"},"member_count":{"type":"number"},"top_component_id":{"type":"string","nullable":true,"description":"Component of the observed top option (variant ids like `control` repeat across components)."},"top_variant_id":{"type":"string","nullable":true,"description":"Observed top variant among members, per (component, variant); null until an arm has 100 exposed member sessions."},"top_variant_visitors":{"type":"number","nullable":true,"description":"Exposed human member sessions on the top option."},"top_variant_conversions":{"type":"number","nullable":true,"description":"Of those, sessions with a goal at/after their first exposure."},"top_variant_cvr":{"type":"number","nullable":true,"description":"Observed conversion rate = conversions ÷ visitors. Descriptive, not the optimizer belief."},"top_variant_avg_reward":{"type":"number","nullable":true,"deprecated":true,"description":"Deprecated alias of top_variant_cvr."}},"additionalProperties":true},"description":"Clusters ordered by member count"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/clusters/{clusterId}/sessions":{"get":{"operationId":"getMgmtProjectsByIdClustersByClusterIdSessions","summary":"Reliable human sessions belonging to one cluster (audience drill-down)","tags":["mgmt"],"description":"Reliable human sessions belonging to one cluster (audience drill-down). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."},{"schema":{"type":"string"},"in":"path","name":"clusterId","required":true,"description":"Cluster id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"sessions":{"type":"array","items":{"type":"object","additionalProperties":true}},"nextCursor":{"type":"string","nullable":true,"description":"Keyset cursor (last_seen_at) for the next page, or null on the last page."}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slots":{"get":{"operationId":"getMgmtProjectsByIdSlots","summary":"Per-slot summary of what each visitor type sees","tags":["mgmt"],"description":"Two different time bases, each stated in the response. `arms` (times shown, conversions, evidence) are the optimizer's cumulative posterior counts — ALL TIME by nature, whatever range is asked for (`evidence_window`). `window_totals` are visitors served and converted inside the requested range (`window`), and so is each slot's `personalizedShare` (share of human decisions inside the range that were personalized). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default all). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Per-slot arm and persona breakdown","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true,"description":"Per-slot arm and persona breakdown"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-trends":{"get":{"operationId":"getMgmtProjectsByIdSlotTrends","summary":"Per-arm trend direction + per-slot conversion sparkline","tags":["mgmt"],"description":"Per-arm trend direction + per-slot conversion sparkline. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default 30d). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Slot trends","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true,"description":"Slot trends"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/suggestions":{"get":{"operationId":"getMgmtProjectsByIdSuggestions","summary":"Rule-based next-step suggestions","tags":["mgmt"],"description":"Rule-based next-step suggestions. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Suggestion cards","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true,"description":"Suggestion cards"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-engagement":{"get":{"operationId":"getMgmtProjectsByIdSlotEngagement","summary":"Section-level behaviour signals per no-code experience","tags":["mgmt"],"description":"Section-level behaviour signals per no-code experience. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default 7d). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"slots":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-definitions":{"get":{"operationId":"getMgmtProjectsByIdSlotDefinitions","summary":"List slot definitions","tags":["mgmt"],"description":"List slot definitions. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Draft + published slot definitions for the project","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true,"description":"Draft + published slot definitions for the project"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-definitions/{slotId}":{"put":{"operationId":"putMgmtProjectsByIdSlotDefinitionsBySlotId","summary":"Create or update a slot draft","tags":["mgmt"],"description":"Create or update a slot draft. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["kind","draftConfig"],"description":"The slot draft to create or replace at :slotId. Saved as a draft; publish separately to serve it.","properties":{"kind":{"type":"string","description":"Slot type — 'tokens' (style-token variants) or 'arms' (content/component variants)."},"target":{"type":"object","description":"Compound element locator for the slot. Omit/null to target the document root (<html>).","additionalProperties":true},"goal":{"type":"string","nullable":true,"description":"Goal id this slot optimizes toward (max 128 chars). OMITTED keeps the existing binding on an update; send null explicitly to unbind."},"displayName":{"type":"string","nullable":true,"description":"Human-readable slot name shown across the dashboard. Falls back to a humanized slot id when omitted."},"draftConfig":{"type":"object","description":"The draft configuration (arms or tokens); validated structurally against `kind`.","additionalProperties":true}},"additionalProperties":true}}},"description":"The slot draft to create or replace at :slotId. Saved as a draft; publish separately to serve it."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-definitions/{slotId}/publish":{"post":{"operationId":"postMgmtProjectsByIdSlotDefinitionsBySlotIdPublish","summary":"Publish a slot draft","tags":["mgmt"],"description":"Publish a slot draft. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Slot published","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"publishedVersion":{"type":"number"}},"additionalProperties":true,"description":"Slot published"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-definitions/{slotId}/pin":{"post":{"operationId":"postMgmtProjectsByIdSlotDefinitionsBySlotIdPin","summary":"Set or clear a slot pin","tags":["mgmt"],"description":"Set or clear a slot pin. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["scope","arm"],"description":"Pin an audience scope to a specific published arm, or clear the pin. Takes effect immediately.","properties":{"scope":{"type":"string","description":"Audience scope — 'all' is a kill-switch across everyone; otherwise a persona key (max 64 chars)."},"arm":{"type":"string","nullable":true,"description":"Arm to pin the scope to; must exist in the published config. Null clears the pin (max 128 chars)."}},"additionalProperties":true}}},"description":"Pin an audience scope to a specific published arm, or clear the pin. Takes effect immediately."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-definitions/{slotId}/archive":{"post":{"operationId":"postMgmtProjectsByIdSlotDefinitionsBySlotIdArchive","summary":"Archive a slot","tags":["mgmt"],"description":"Archive a slot. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-definitions/{slotId}/unarchive":{"post":{"operationId":"postMgmtProjectsByIdSlotDefinitionsBySlotIdUnarchive","summary":"Restore an archived slot","tags":["mgmt"],"description":"Restore an archived slot. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-definitions/{slotId}/rollback":{"post":{"operationId":"postMgmtProjectsByIdSlotDefinitionsBySlotIdRollback","summary":"Roll a slot back to a prior published version","tags":["mgmt"],"description":"Roll a slot back to a prior published version. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["toVersion"],"description":"Republish a prior version as a new version (append-only). Pins that do not fit the restored options are cleared.","properties":{"toVersion":{"type":"integer","description":"The version to restore."}},"additionalProperties":true}}},"description":"Republish a prior version as a new version (append-only). Pins that do not fit the restored options are cleared."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Rolled back","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"publishedVersion":{"type":"number"}},"additionalProperties":true,"description":"Rolled back"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-definitions/{slotId}/history":{"get":{"operationId":"getMgmtProjectsByIdSlotDefinitionsBySlotIdHistory","summary":"Version + decision history for a slot","tags":["mgmt"],"description":"Version + decision history for a slot. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Retained versions and the decision ledger for this slot","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Retained versions and the decision ledger for this slot"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-definitions/{slotId}/baseline-text":{"get":{"operationId":"getMgmtProjectsByIdSlotDefinitionsBySlotIdBaselineText","summary":"A slot's grounding text and the visitor-reported candidates","tags":["mgmt"],"description":"A slot's grounding text and the visitor-reported candidates. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Stored baselineText (with its source) and pending candidates with distinct-network backing","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Stored baselineText (with its source) and pending candidates with distinct-network backing"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"operationId":"putMgmtProjectsByIdSlotDefinitionsBySlotIdBaselineText","summary":"Confirm or override a slot's grounding text","tags":["mgmt"],"description":"Confirm or override a slot's grounding text. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text"],"description":"Owner-set text always wins: visitor votes never replace it. null clears the stored text and re-opens visitor voting.","properties":{"text":{"type":"string","description":"What the region says today (≤400 chars kept).","nullable":true}},"additionalProperties":true}}},"description":"Owner-set text always wins: visitor votes never replace it. null clears the stored text and re-opens visitor voting."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-definitions/{slotId}/authored-arms/{armKey}":{"put":{"operationId":"putMgmtProjectsByIdSlotDefinitionsBySlotIdAuthoredArmsByArmKey","summary":"Override an authored arm's recorded text","tags":["mgmt"],"description":"Override an authored arm's recorded text. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text"],"properties":{"text":{"type":"string","nullable":true}},"additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot identifier, unique within the project (1–128 chars)."},{"schema":{"type":"string"},"in":"path","name":"armKey","required":true,"description":"The authored arm key."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/repo-connection":{"get":{"operationId":"getMgmtProjectsByIdRepoConnection","summary":"The GitHub repo bound to this project (verified-PR path)","tags":["mgmt"],"description":"The GitHub repo bound to this project (verified-PR path). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"connected":{"type":"boolean"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"operationId":"putMgmtProjectsByIdRepoConnection","summary":"Bind one GitHub repo to this project","tags":["mgmt"],"description":"Bind one GitHub repo to this project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["installationId","repoOwner","repoName"],"properties":{"installationId":{"type":"number","description":"GitHub App installation id."},"repoOwner":{"type":"string"},"repoName":{"type":"string"},"defaultBranch":{"type":"string","description":"Defaults to the repo's default branch as GitHub reports it."}}}}}},"security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteMgmtProjectsByIdRepoConnection","summary":"Remove the repo binding","tags":["mgmt"],"description":"Remove the repo binding. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/repo-installations/{installationId}/repos":{"get":{"operationId":"getMgmtRepoInstallationsByInstallationIdRepos","summary":"Repos accessible to a GitHub App installation (connect page)","tags":["mgmt"],"description":"Repos accessible to a GitHub App installation (connect page). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"installationId","required":true,"description":"Installation id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"repos":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/pr-jobs":{"post":{"operationId":"postMgmtProjectsByIdPrJobs","summary":"Queue a verified-PR job for one detected element","tags":["mgmt"],"description":"Queue a verified-PR job for one detected element. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["targetId","label","goalId","arms"],"properties":{"targetId":{"type":"string","description":"Detected element id from the site audit."},"label":{"type":"string"},"goalId":{"type":"string","description":"Goal the test optimises — written into the committed wiring."},"arms":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"getMgmtProjectsByIdPrJobs","summary":"Recent verified-PR jobs for the project","tags":["mgmt"],"description":"Recent verified-PR jobs for the project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"jobs":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/pr-jobs/{jobId}":{"get":{"operationId":"getMgmtProjectsByIdPrJobsByJobId","summary":"One verified-PR job","tags":["mgmt"],"description":"One verified-PR job. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."},{"schema":{"type":"string"},"in":"path","name":"jobId","required":true,"description":"Job id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/preview-support":{"get":{"operationId":"getMgmtProjectsByIdPreviewSupport","summary":"Whether the project site can be embedded for in-dashboard preview","tags":["mgmt"],"description":"Whether the project site can be embedded for in-dashboard preview. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"origin":{"type":"string","nullable":true,"description":"Primary https origin, or null when none is allow-listed."},"frameable":{"type":"boolean"},"reason":{"type":"string","description":"ok | x_frame_options | csp_frame_ancestors | unreachable"}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-definitions/{slotId}/drift":{"get":{"operationId":"getMgmtProjectsByIdSlotDefinitionsBySlotIdDrift","summary":"Whether a slot still points at its element on the live page","tags":["mgmt"],"description":"Whether a slot still points at its element on the live page. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."},{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"verdict":{"type":"string"},"message":{"type":"string"},"checkedUrl":{"type":"string","nullable":true}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/composition-arrangements":{"get":{"operationId":"getMgmtProjectsByIdCompositionArrangements","summary":"List the composition arrangement catalog","tags":["mgmt"],"description":"List the composition arrangement catalog. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"The designer-authored arrangement catalog (hero, cta_band, feature_grid, testimonial, pricing, comparison, faq, logos, stats), ordered converter-first.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"arrangements":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"sectionType":{"type":"string"},"role":{"type":"string","description":"Section-taxonomy role ('converter' | 'persuader'); the list is ordered converter-first."},"name":{"type":"string"},"description":{"type":"string"},"fields":{"type":"array","items":{"type":"object","additionalProperties":true}},"tree":{"type":"object","additionalProperties":true,"description":"Block tree with {{fieldId}} placeholders (for previews/thumbnails)."}},"additionalProperties":true}}},"additionalProperties":true,"description":"The designer-authored arrangement catalog (hero, cta_band, feature_grid, testimonial, pricing, comparison, faq, logos, stats), ordered converter-first."}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/composition-arrangements/{arrangementId}/instantiate":{"post":{"operationId":"postMgmtProjectsByIdCompositionArrangementsByArrangementIdInstantiate","summary":"Instantiate an arrangement with field values","tags":["mgmt"],"description":"Instantiate an arrangement with field values. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Fill an arrangement's fields and get back a total-validated Composition Block tree, ready to save as an arm's `blocks` via the slot-definitions draft. Text fields fall back to their defaults; link fields are required.","properties":{"fields":{"type":"object","additionalProperties":{"type":"string"},"description":"fieldId → value. See the catalog listing for each arrangement’s fields."}},"additionalProperties":true}}},"description":"Fill an arrangement's fields and get back a total-validated Composition Block tree, ready to save as an arm's `blocks` via the slot-definitions draft. Text fields fall back to their defaults; link fields are required."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."},{"schema":{"type":"string"},"in":"path","name":"arrangementId","required":true,"description":"Arrangement id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"The instantiated, validated block tree.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"blocks":{"type":"object","additionalProperties":true}},"additionalProperties":true,"description":"The instantiated, validated block tree."}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-suggest":{"post":{"operationId":"postMgmtProjectsByIdSlotSuggest","summary":"Suggest adaptive slots from a plain-English intent","tags":["mgmt"],"description":"Suggest adaptive slots from a plain-English intent. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["intent"],"properties":{"intent":{"type":"string","description":"What the user wants to make adaptive (1–500 chars)."},"targetHint":{"type":"object","additionalProperties":true,"description":"Picked-element locator + hints when no audit exists."}},"additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"kind:\"suggestions\" with editable drafts, or kind:\"error\" with a reason.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"kind:\"suggestions\" with editable drafts, or kind:\"error\" with a reason."}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slots/{slotId}/generation-depth":{"patch":{"operationId":"patchMgmtProjectsByIdSlotsBySlotIdGenerationDepth","summary":"How deep generation goes for one region: automatic, rewrite the copy, or redesign the section","tags":["mgmt"],"description":"How deep generation goes for one region: automatic, rewrite the copy, or redesign the section. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["depth"],"properties":{"depth":{"type":"string","enum":["auto","rewrite","redesign"]}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"slotId","required":true,"description":"Slot id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/cells":{"get":{"operationId":"getMgmtProjectsByIdCells","summary":"Persona × slot cell matrix: slots, personas, and generation state","tags":["mgmt"],"description":"Persona × slot cell matrix: slots, personas, and generation state. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/cells/detail":{"get":{"operationId":"getMgmtProjectsByIdCellsDetail","summary":"One cell's option, rationale, and plain-language performance verdict","tags":["mgmt"],"description":"One cell's option, rationale, and plain-language performance verdict. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/cells/generate":{"post":{"operationId":"postMgmtProjectsByIdCellsGenerate","summary":"Queue AI generation of one (persona, slot) cell","tags":["mgmt"],"description":"Queue AI generation of one (persona, slot) cell. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["slotId","persona"],"properties":{"slotId":{"type":"string"},"persona":{"type":"string"}},"additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"202":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/cells/generate-all":{"post":{"operationId":"postMgmtProjectsByIdCellsGenerateAll","summary":"Queue AI generation for every unfilled cell","tags":["mgmt"],"description":"Queue AI generation for every unfilled cell. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"202":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/cells/auto-fill":{"post":{"operationId":"postMgmtProjectsByIdCellsAutoFill","summary":"Enable/disable first-miss auto-generation for this project","tags":["mgmt"],"description":"Enable/disable first-miss auto-generation for this project. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enabled"],"properties":{"enabled":{"type":"boolean"}},"additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/cells/review-mode":{"post":{"operationId":"postMgmtProjectsByIdCellsReviewMode","summary":"Enable/disable human review before generated versions publish","tags":["mgmt"],"description":"Enable/disable human review before generated versions publish. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enabled"],"properties":{"enabled":{"type":"boolean"}},"additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/cell-reviews":{"get":{"operationId":"getMgmtProjectsByIdCellReviews","summary":"Generated versions waiting for approval, with the palette for preview","tags":["mgmt"],"description":"Generated versions waiting for approval, with the palette for preview. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/cells/review":{"post":{"operationId":"postMgmtProjectsByIdCellsReview","summary":"Approve (publish) or reject one generated version awaiting review","tags":["mgmt"],"description":"Approve (publish) or reject one generated version awaiting review. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["slotId","persona","action"],"properties":{"slotId":{"type":"string"},"persona":{"type":"string"},"action":{"type":"string","enum":["approve","reject"]},"feedback":{"type":"string","description":"Optional reviewer note stored with a rejection."}},"additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/generation-stats":{"get":{"operationId":"getMgmtProjectsByIdGenerationStats","summary":"Generation health: today's spend vs cap, 30-day outcomes by reason, pending reviews","tags":["mgmt"],"description":"Generation health: today's spend vs cap, 30-day outcomes by reason, pending reviews. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/generated-impact":{"get":{"operationId":"getMgmtProjectsByIdGeneratedImpact","summary":"Credited conversions for generated versions vs originals (+ AOV estimate inputs)","tags":["mgmt"],"description":"Credited conversions for generated versions vs originals (+ AOV estimate inputs). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"generated":{"type":"object","properties":{"exposures":{"type":"number","description":"Credited trials (slot_weights global cell) — the optimizer's count"},"conversions":{"type":"number","description":"Credited REWARD summed over those trials: fractional, and summed across goals — not a count of converting visits"},"visitors":{"type":"integer","description":"Distinct human sessions with a closed, non-pinned, non-holdout decision on these arms"},"converted":{"type":"integer","description":"Of those visitors, the ones with a conversion goal at or after that decision"}},"additionalProperties":true},"baseline":{"type":"object","properties":{"exposures":{"type":"number","description":"Credited trials (slot_weights global cell) — the optimizer's count"},"conversions":{"type":"number","description":"Credited REWARD summed over those trials: fractional, and summed across goals — not a count of converting visits"},"visitors":{"type":"integer","description":"Distinct human sessions with a closed, non-pinned, non-holdout decision on these arms"},"converted":{"type":"integer","description":"Of those visitors, the ones with a conversion goal at or after that decision"}},"additionalProperties":true},"avgOrderValue":{"type":"number","nullable":true},"currency":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/style-vocabulary":{"get":{"operationId":"getMgmtProjectsByIdStyleVocabulary","summary":"The site's captured styles (what redesigned sections borrow), with when each source last captured","tags":["mgmt"],"description":"The site's captured styles (what redesigned sections borrow), with when each source last captured. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/style-vocabulary/{entryId}":{"delete":{"operationId":"deleteMgmtProjectsByIdStyleVocabularyByEntryId","summary":"Remove one captured style; it is never re-captured","tags":["mgmt"],"description":"Remove one captured style; it is never re-captured. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"entryId","required":true,"description":"Entry id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/decided":{"get":{"operationId":"getMgmtProjectsByIdDecided","summary":"Review › Decided: past decisions on what visitors see, newest first","tags":["mgmt"],"description":"Approvals and rejections of generated versions, publishes (including automatic ones), pins, rollbacks, pauses (including guardrail auto-pauses still in effect), promotions and migrations, and changes to the approval and auto-fill switches, with who decided, when and the recorded reason. Keyset-paged: pass `nextCursor` back as `cursor`. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Opaque cursor from a previous page."},{"schema":{"type":"string"},"in":"query","name":"limit","required":false,"description":"Entries per page (1–100, default 25)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"decisions":{"type":"array","items":{"type":"object","additionalProperties":true}},"nextCursor":{"type":"string","nullable":true}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/serving-record/surfaces":{"get":{"operationId":"getMgmtProjectsByIdServingRecordSurfaces","summary":"Serving record: surfaces with recent decisions","tags":["mgmt"],"description":"Slots and the page layout, each with its decision count over the last 30 days. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/serving-record":{"get":{"operationId":"getMgmtProjectsByIdServingRecord","summary":"Serving record: one surface, newest first","tags":["mgmt"],"description":"Each decision with the option shown, its chance at that moment, every option's chance (from migration 163), why it was chosen, and the outcome close-out recorded. Visitor ids are one-way hashes. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/serving-record/export.csv":{"get":{"operationId":"getMgmtProjectsByIdServingRecordExportCsv","summary":"Serving record: download one surface as CSV","tags":["mgmt"],"description":"Every decision for the surface, newest first, same fields as the page. Capped at 250,000 rows; the last line says so when the cap is hit. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/serving-record/tally":{"get":{"operationId":"getMgmtProjectsByIdServingRecordTally","summary":"Serving record: per-option tally","tags":["mgmt"],"description":"How often each option was shown in the last 30 days, and why. Counts only. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/structured-insights":{"get":{"operationId":"getMgmtProjectsByIdStructuredInsights","summary":"List structured insights","tags":["mgmt"],"description":"List structured insights. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Structured insights (empty + plan_required on Free/Starter)","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Structured insights (empty + plan_required on Free/Starter)"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/structured-insights/{insightId}/dismiss":{"post":{"operationId":"postMgmtProjectsByIdStructuredInsightsByInsightIdDismiss","summary":"Dismiss a structured insight","tags":["mgmt"],"description":"Dismiss a structured insight. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Dismiss with an optional reason; suppresses the same insight for suppressDays (default 30).","properties":{"reason":{"type":"string","nullable":true},"suppressDays":{"type":"integer"}},"additionalProperties":true}}},"description":"Dismiss with an optional reason; suppresses the same insight for suppressDays (default 30)."},"security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."},{"schema":{"type":"string"},"in":"path","name":"insightId","required":true,"description":"Insight id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/structured-insights/{insightId}/save":{"post":{"operationId":"postMgmtProjectsByIdStructuredInsightsByInsightIdSave","summary":"Save a structured insight","tags":["mgmt"],"description":"Save a structured insight. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."},{"schema":{"type":"string"},"in":"path","name":"insightId","required":true,"description":"Insight id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/structured-insights/{insightId}/accept":{"post":{"operationId":"postMgmtProjectsByIdStructuredInsightsByInsightIdAccept","summary":"Save a structured insight","tags":["mgmt"],"description":"Save a structured insight. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."},{"schema":{"type":"string"},"in":"path","name":"insightId","required":true,"description":"Insight id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/evidence-report":{"get":{"operationId":"getMgmtProjectsByIdEvidenceReport","summary":"What we know about this project, at the confidence earned","tags":["mgmt"],"description":"What we know about this project, at the confidence earned. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Ranked findings with provenance, plus emptyReason when there are none","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"reached":{"type":"string","description":"observed | patterned | tested"}},"additionalProperties":true,"description":"Ranked findings with provenance, plus emptyReason when there are none"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/evidence-report/export":{"get":{"operationId":"getMgmtProjectsByIdEvidenceReportExport","summary":"Export the evidence report as CSV or JSON","tags":["mgmt"],"description":"Downloads the plan-gated evidence report — findings with provenance (sample, what it counts, coverage, window, method) in plain language. `format=csv` (default) or `format=json`. Gated findings are stripped server-side, exactly as on the page. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string","enum":["csv","json"]},"in":"query","name":"format","required":false,"description":"Export format (default csv)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/performance-outcomes":{"get":{"operationId":"getMgmtProjectsByIdPerformanceOutcomes","summary":"Outcome-led performance summary","tags":["mgmt"],"description":"Outcome-led performance summary. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Goal + lift vs control + traffic + recent changes","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Goal + lift vs control + traffic + recent changes"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/goal-definitions":{"get":{"operationId":"getMgmtProjectsByIdGoalDefinitions","summary":"List goal definitions","tags":["mgmt"],"description":"List goal definitions. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Active and archived goal definitions","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"goals":{"type":"array","items":{"type":"object","properties":{"goal_id":{"type":"string"},"display_name":{"type":"string"},"role":{"type":"string"},"event":{"type":"string"},"url_pattern":{"type":"string","nullable":true},"slot_id":{"type":"string","nullable":true},"status":{"type":"string"},"source":{"type":"string","nullable":true},"auditTargetId":{"type":"string","nullable":true},"baseline":{"type":"object","additionalProperties":true,"nullable":true},"default_value":{"type":"string","nullable":true,"description":"Fixed worth applied when an event carries no explicit value (NUMERIC, serialized as string)"},"value_reference":{"type":"string","nullable":true,"description":"Manual reference value overriding the rolling p90 (NUMERIC, serialized as string)"},"threshold":{"type":"string","nullable":true,"description":"scroll_depth goals: how far down the page counts (NUMERIC, serialized as string)"}},"additionalProperties":true}}},"additionalProperties":true,"description":"Active and archived goal definitions"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"postMgmtProjectsByIdGoalDefinitions","summary":"Create a goal (never overwrites, never primary)","tags":["mgmt"],"description":"Creates an active goal at `goalId`. Fails with 409 `goal_exists` when any goal (active, draft or archived) already has that id — it never modifies an existing goal. Never assigns or changes the primary goal: `role` may be 'secondary' (default) or 'guardrail'; 'primary' is rejected with 400 `primary_not_allowed` (set it with the role endpoint). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["goalId","event"],"properties":{"goalId":{"type":"string","description":"New goal identifier, unique within the project (1–128 chars)."},"event":{"type":"string","description":"One of 'click', 'form_submit', 'url_reached', 'scroll_depth'."},"displayName":{"type":"string","nullable":true,"description":"Human-readable name. Falls back to a humanized goal id."},"role":{"type":"string","description":"secondary (default) | guardrail. 'primary' is rejected."},"locator":{"type":"object","additionalProperties":true,"description":"Element locator for click/form_submit goals."},"urlPattern":{"type":"string","nullable":true,"description":"URL pattern for url_reached goals (max 512 chars)."},"threshold":{"type":"number","nullable":true,"description":"scroll_depth goals: how far down the page counts, in (0, 1]."},"defaultValue":{"type":"number","nullable":true,"description":"Fixed worth applied when a conversion carries no value."}},"additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"201":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"goalId":{"type":"string"},"role":{"type":"string","description":"secondary | guardrail — never primary"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/goal-definitions/{goalId}":{"put":{"operationId":"putMgmtProjectsByIdGoalDefinitionsByGoalId","summary":"Create or update a goal","tags":["mgmt"],"description":"Create or update a goal. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event"],"description":"The goal definition to create or replace at :goalId.","properties":{"event":{"type":"string","description":"Conversion signal to track — one of 'click', 'form_submit', 'url_reached', 'scroll_depth'."},"threshold":{"type":"number","nullable":true,"description":"For scroll_depth goals: how far down the page counts, in (0, 1]."},"displayName":{"type":"string","nullable":true,"description":"Human-readable goal name shown across the dashboard. Falls back to a humanized goal id when omitted."},"role":{"type":"string","description":"primary | secondary | guardrail. Setting primary demotes the current primary. Defaults to secondary."},"locator":{"type":"object","description":"Compound element locator identifying the tracked element (for click/form_submit). Optional.","additionalProperties":true},"urlPattern":{"type":"string","nullable":true,"description":"URL pattern matched for url_reached goals (max 512 chars). Null/omitted for element goals."},"slotId":{"type":"string","nullable":true,"description":"Slot this goal is attributed to (max 128 chars). Null/omitted if not slot-scoped."}},"additionalProperties":true}}},"description":"The goal definition to create or replace at :goalId."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"goalId","required":true,"description":"Goal identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/goal-definitions/{goalId}/role":{"post":{"operationId":"postMgmtProjectsByIdGoalDefinitionsByGoalIdRole","summary":"Set a goal role (primary/secondary/guardrail)","tags":["mgmt"],"description":"Set a goal role (primary/secondary/guardrail). Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["role"],"description":"Set the goal role. Setting primary demotes the project's current primary.","properties":{"role":{"type":"string","description":"primary | secondary | guardrail."}},"additionalProperties":true}}},"description":"Set the goal role. Setting primary demotes the project's current primary."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"goalId","required":true,"description":"Goal identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/goal-definitions/{goalId}/publish":{"post":{"operationId":"postMgmtProjectsByIdGoalDefinitionsByGoalIdPublish","summary":"Publish a draft goal","tags":["mgmt"],"description":"Publish a draft goal. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"goalId","required":true,"description":"Goal identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/goal-definitions/{goalId}/archive":{"post":{"operationId":"postMgmtProjectsByIdGoalDefinitionsByGoalIdArchive","summary":"Archive a goal","tags":["mgmt"],"description":"Archive a goal. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"goalId","required":true,"description":"Goal identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/goal-definitions/{goalId}/unarchive":{"post":{"operationId":"postMgmtProjectsByIdGoalDefinitionsByGoalIdUnarchive","summary":"Restore an archived goal","tags":["mgmt"],"description":"Restore an archived goal. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"goalId","required":true,"description":"Goal identifier, unique within the project (1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/editor-token":{"post":{"operationId":"postMgmtProjectsByIdEditorToken","summary":"Mint a visual-editor token","tags":["mgmt"],"description":"Mint a visual-editor token. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Editor token issued","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","description":"One-time, 60 s exchange code. Put it in the URL FRAGMENT (`#sentient_editor_code=`), never the query; the on-site editor exchanges it at POST /v1/editor/exchange."},"codeExpiresInMs":{"type":"integer","description":"Code lifetime in milliseconds"},"token":{"type":"string","description":"Deprecated: the editor token itself. Kept one release so a dashboard deployed before this API keeps working; never put it in a URL."},"expiresInMs":{"type":"integer","description":"Token lifetime in milliseconds"}},"additionalProperties":true,"description":"Editor token issued"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/preview-token":{"post":{"operationId":"postMgmtProjectsByIdPreviewToken","summary":"Mint a draft-preview token","tags":["mgmt"],"description":"Five-minute, read-only token that lets `POST /v1/explain` resolve this project's DRAFT slots (`includeDrafts` + `previewToken`) for the dashboard preview iframe. Cannot edit or publish. Any role that can see the project may mint one. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Preview token issued","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Short-lived preview-read token"},"expiresInMs":{"type":"integer","description":"Token lifetime in milliseconds"}},"additionalProperties":true,"description":"Preview token issued"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/goal-builder":{"post":{"operationId":"postMgmtProjectsByIdGoalBuilder","summary":"Draft a goal from a plain-English conversation","tags":["mgmt"],"description":"Draft a goal from a plain-English conversation. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Send the full conversation as `messages` to continue a thread; a single `message` string is accepted for the first turn. The last turn must be from the user.","properties":{"messages":{"type":"array","description":"Conversation history (1–20 turns). The last turn must have role \"user\".","items":{"type":"object","required":["role","content"],"properties":{"role":{"type":"string","description":"Turn author — 'user' or 'assistant'."},"content":{"type":"string","description":"Turn text (1–2000 chars)."}},"additionalProperties":true}},"message":{"type":"string","description":"Single user message (1–1000 chars); backward-compatible shorthand for a one-turn `messages`."}},"additionalProperties":true}}},"description":"Send the full conversation as `messages` to continue a thread; a single `message` string is accepted for the first turn. The last turn must be from the user."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"A clarifying question, one or more proposed goal drafts, or an error reason","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","description":"question | draft | error"},"question":{"type":"string","description":"A single clarifying question (kind=question)"},"drafts":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Proposed goal drafts (kind=draft). One intent may cover several elements, e.g. \"track both contact forms\"."},"reason":{"type":"string","description":"Why no goal could be drafted (kind=error)"},"assistantMessage":{"type":"string","description":"Raw assistant text to append to the conversation history"}},"additionalProperties":true,"description":"A clarifying question, one or more proposed goal drafts, or an error reason"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/funnels":{"get":{"operationId":"getMgmtProjectsByIdFunnels","summary":"List funnels","tags":["mgmt"],"description":"List funnels. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Funnel definitions with ordered steps and assigned components","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"funnels":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true,"description":"Funnel definitions with ordered steps and assigned components"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/funnels/{funnelId}":{"put":{"operationId":"putMgmtProjectsByIdFunnelsByFunnelId","summary":"Create or update a funnel","tags":["mgmt"],"description":"Create or update a funnel. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["displayName","steps"],"description":"The funnel definition to create or replace at :funnelId. Steps are ordered; each references a goal id.","properties":{"displayName":{"type":"string","description":"Human-readable funnel name."},"windowDays":{"type":"integer","description":"Conversion window in days (default 30)."},"strictOrder":{"type":"boolean","description":"Report a step only when the previous step happened first. Defaults true; set false to count a set of related-but-unordered goals. Reporting only — training always credits max progress."},"guardrailGoalId":{"type":"string","nullable":true,"description":"A goal with role='guardrail' this funnel protects; breaching variants on member components are auto-paused."},"status":{"type":"string","description":"'draft' | 'active' (default active). Archive via the archive endpoint."},"steps":{"type":"array","description":"Ordered steps (2–12). Each step is an existing goal id; optional weight overrides the automatic end-weighted credit and must not decrease along the funnel.","items":{"type":"object","additionalProperties":true}},"components":{"type":"array","description":"Components/slots serving this funnel, optionally pinned to a step index.","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}},"description":"The funnel definition to create or replace at :funnelId. Steps are ordered; each references a goal id."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"funnelId","required":true,"description":"Funnel slug, unique within the project (lowercase, 1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/funnels/{funnelId}/report":{"get":{"operationId":"getMgmtProjectsByIdFunnelsByFunnelIdReport","summary":"Funnel drop-off report","tags":["mgmt"],"description":"Funnel drop-off report. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"funnelId","required":true,"description":"Funnel slug, unique within the project (lowercase, 1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Per-step reach, drop-off, variant/persona splits, final-step revenue","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"funnelId":{"type":"string"},"displayName":{"type":"string"},"windowDays":{"type":"integer"},"strictOrder":{"type":"boolean"},"currency":{"type":"string"},"steps":{"type":"array","items":{"type":"object","additionalProperties":true}},"revenue":{"type":"number","nullable":true},"avgOrderValue":{"type":"number","nullable":true},"revenuePerEnteringVisitor":{"type":"number","nullable":true},"holdoutCompletion":{"type":"object","additionalProperties":true,"nullable":true}},"additionalProperties":true,"description":"Per-step reach, drop-off, variant/persona splits, final-step revenue"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/funnels/{funnelId}/archive":{"post":{"operationId":"postMgmtProjectsByIdFunnelsByFunnelIdArchive","summary":"Archive a funnel","tags":["mgmt"],"description":"Archive a funnel. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"funnelId","required":true,"description":"Funnel slug, unique within the project (lowercase, 1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/funnels/{funnelId}/unarchive":{"post":{"operationId":"postMgmtProjectsByIdFunnelsByFunnelIdUnarchive","summary":"Restore an archived funnel","tags":["mgmt"],"description":"Restore an archived funnel. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"funnelId","required":true,"description":"Funnel slug, unique within the project (lowercase, 1–128 chars)."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/goal-warnings":{"get":{"operationId":"getMgmtProjectsByIdGoalWarnings","summary":"List goal-name typo warnings","tags":["mgmt"],"description":"List goal-name typo warnings. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Undismissed near-duplicate goal names with their suggested canonical goal","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"warnings":{"type":"array","items":{"type":"object","properties":{"goalName":{"type":"string"},"suggestion":{"type":"string"},"firstSeen":{"type":"string"},"conversions":{"type":"integer","description":"Conversions under the flagged name in the last 7 days."}},"additionalProperties":true}}},"additionalProperties":true,"description":"Undismissed near-duplicate goal names with their suggested canonical goal"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/goal-warnings/{goalName}/dismiss":{"post":{"operationId":"postMgmtProjectsByIdGoalWarningsByGoalNameDismiss","summary":"Dismiss a goal-name warning","tags":["mgmt"],"description":"Dismiss a goal-name warning. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"goalName","required":true,"description":"The flagged (suspected-typo) goal name."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/goal-warnings/{goalName}/alias":{"post":{"operationId":"postMgmtProjectsByIdGoalWarningsByGoalNameAlias","summary":"Declare a flagged goal name an alias of its suggested goal","tags":["mgmt"],"description":"Declare a flagged goal name an alias of its suggested goal. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"goalName","required":true,"description":"The flagged (suspected-typo) goal name."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"The alias was appended to the canonical goal and the warning dismissed","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"canonical":{"type":"string"}},"additionalProperties":true,"description":"The alias was appended to the canonical goal and the warning dismissed"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/home-summary":{"get":{"operationId":"getMgmtProjectsByIdHomeSummary","summary":"Dashboard home summary","tags":["mgmt"],"description":"Dashboard home summary. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Cold/learning/ready state with lift, learning progress, and readiness","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"state":{"type":"string","description":"cold | learning | ready"}},"additionalProperties":true,"description":"Cold/learning/ready state with lift, learning progress, and readiness"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/site-audit":{"get":{"operationId":"getMgmtProjectsByIdSiteAudit","summary":"Get the latest site audit","tags":["mgmt"],"description":"Get the latest site audit. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Audit status and, when complete, the report","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"crawlable":{"type":"boolean","nullable":true,"description":"Whether a public origin exists so a crawl-based audit can run (present on pending responses)"},"checking":{"type":"boolean","nullable":true,"description":"Whether a crawl is queued or running right now (a refresh was requested and the worker has not finished it)"},"overallScore":{"type":"number","nullable":true},"auditedAt":{"type":"string","nullable":true,"description":"ISO 8601 timestamp"},"error":{"type":"string","nullable":true}},"additionalProperties":true,"description":"Audit status and, when complete, the report"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/site-audit/refresh":{"post":{"operationId":"postMgmtProjectsByIdSiteAuditRefresh","summary":"Queue a site audit re-run","tags":["mgmt"],"description":"Queue a site audit re-run. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID"}],"security":[{"secretKey":[]}],"responses":{"202":{"description":"Audit re-run queued","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"}},"additionalProperties":true,"description":"Audit re-run queued"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/page-semantics":{"get":{"operationId":"getMgmtProjectsByIdPageSemantics","summary":"Page understanding: classified sections + trait coverage meter","tags":["mgmt"],"description":"Page understanding: classified sections + trait coverage meter. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Coverage meter + per-page sections","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Coverage meter + per-page sections"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"patchMgmtProjectsByIdPageSemantics","summary":"Confirm, correct, or reject a classified page section","tags":["mgmt"],"description":"Confirm, correct, or reject a classified page section. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["pageUrl","sectionKey","action"],"properties":{"pageUrl":{"type":"string"},"sectionKey":{"type":"string"},"action":{"type":"string","enum":["confirm","reject","change"]},"type":{"type":"string","enum":["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"],"description":"Required for action=change."}},"additionalProperties":true}}}},"security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/feedback":{"post":{"operationId":"postMgmtFeedback","summary":"Submit product feedback","tags":["mgmt"],"description":"Submit product feedback. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["source"],"description":"One feedback submission from any dashboard surface.","properties":{"source":{"type":"string","enum":["general","insight","exit_survey","setup_pulse"]},"projectId":{"type":"string","description":"Project UUID, when the feedback is project-scoped."},"score":{"type":"number","description":"±1 for insight thumbs; 1–5 for the setup pulse."},"reason":{"type":"string","enum":["too_expensive","missing_feature","no_results","project_ended","other"],"description":"Exit-survey reason code."},"comment":{"type":"string"},"context":{"type":"object","additionalProperties":true}},"additionalProperties":true}}},"description":"One feedback submission from any dashboard surface."},"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/prompts":{"get":{"operationId":"getMgmtPrompts","summary":"Read feedback-prompt state","tags":["mgmt"],"description":"Read feedback-prompt state. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"prompts":{"type":"object","additionalProperties":{"type":"string"}}},"additionalProperties":true}}}}}},"post":{"operationId":"postMgmtPrompts","summary":"Dismiss or answer a feedback prompt","tags":["mgmt"],"description":"Dismiss or answer a feedback prompt. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["key","status"],"properties":{"key":{"type":"string"},"status":{"type":"string","enum":["dismissed","answered"]}},"additionalProperties":true}}}},"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/agent-activity/summary":{"get":{"operationId":"getMgmtProjectsByIdAgentActivitySummary","summary":"Agent traffic summary for a project","tags":["mgmt"],"description":"Totals, engine breakdown, top fetched paths, and a daily series for AI agent traffic (passive crawlers, agentic browser sessions, agent API calls). Paid plans only. Agent traffic is never counted in impressions or conversion rate. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default 30d). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Agent traffic summary","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["totals","engines","topPaths","daily","intents","classifiedAgents"],"properties":{"totals":{"type":"object","properties":{"crawler":{"type":"number"},"api":{"type":"number"},"browser":{"type":"number"}}},"engines":{"type":"array","items":{"type":"object","properties":{"engine":{"type":"string"},"intent":{"type":"string"},"count":{"type":"number"},"sharePct":{"type":"number"},"lastSeen":{"type":"string"},"firstSeenInRange":{"type":"boolean"}}}},"intents":{"type":"object","properties":{"user":{"type":"number"},"search":{"type":"number"},"training":{"type":"number"},"other":{"type":"number"}}},"classifiedAgents":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},"topPaths":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"count":{"type":"number"},"engines":{"type":"number"}}}},"daily":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string"},"crawler":{"type":"number"},"api":{"type":"number"},"browser":{"type":"number"}}}},"capture":{"type":"array","description":"Server-side capture paths that have ever reported for this project (all-time). Empty = crawler fetches are not measured on this site.","items":{"type":"object","properties":{"source":{"type":"string"},"lastSeen":{"type":"string"}}}},"siteStack":{"type":"object","nullable":true,"description":"Framework and host detected by the latest site audit, and which capture path fits (adaptive_root | edge | middleware | unavailable | unknown).","properties":{"framework":{"type":"string","nullable":true},"host":{"type":"string","nullable":true},"capture":{"type":"string"},"signals":{"type":"array","items":{"type":"string"}}}},"window":{"type":"object","additionalProperties":true,"description":"The window the server resolved (range, start, end, timezone, retention facts)"}},"description":"Agent traffic summary"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/agent-activity/log":{"get":{"operationId":"getMgmtProjectsByIdAgentActivityLog","summary":"Agent activity log for a project","tags":["mgmt"],"description":"Every observed agent visit, newest first: per-fetch rows for crawlers and agent API calls, per-session rows for agentic browser sessions. Keyset-paginated. Paid plans only. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string","format":"date-time"},"in":"query","name":"before","required":false,"description":"Keyset cursor: return rows older than this timestamp. Pass back the `nextBefore` from the previous page."},{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"limit","required":false,"description":"Rows per page (default 50)."},{"schema":{"type":"string","maxLength":128},"in":"query","name":"engine","required":false,"description":"Only rows from this agent engine, e.g. `GPTBot`."},{"schema":{"type":"string","enum":["crawler","api","browser"]},"in":"query","name":"type","required":false,"description":"Only rows of this activity kind."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Activity log page","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["rows","windowDays"],"properties":{"rows":{"type":"array","items":{"type":"object","additionalProperties":true}},"nextBefore":{"type":"string","nullable":true},"windowDays":{"type":"number","description":"Retention window applied (plan-dependent)"}},"description":"Activity log page"}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/agent-activity/legibility":{"get":{"operationId":"getMgmtProjectsByIdAgentActivityLegibility","summary":"Machine-legibility results for agent-read paths","tags":["mgmt"],"description":"Per-path legibility scores for the pages AI crawlers actually fetch (is your price, name, positioning, CTA present in the server HTML?), plus agent API blocks served without agent data. Paid plans only. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Legibility fix list","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["paths","emptyBlocks"],"properties":{"paths":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"score":{"type":"number"},"checks":{"type":"object","additionalProperties":true},"lastChecked":{"type":"string"},"fixes":{"type":"array","description":"Concrete Next.js remediation per failing check, derived at read time","items":{"type":"object","properties":{"check":{"type":"string"},"advice":{"type":"string"},"snippet":{"type":"string"}}}}}}},"emptyBlocks":{"type":"array","items":{"type":"object","properties":{"block":{"type":"string"},"variant":{"type":"string"},"occurrences":{"type":"number"}}}}},"description":"Legibility fix list"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/geography":{"get":{"operationId":"getMgmtProjectsByIdGeography","summary":"Where a project’s real visitors are","tags":["mgmt"],"description":"Sessions and conversion rate by country over the window, from the country the API derives from the request address at ingest (never the integrator-supplied `country`, which only reflects whether an integration sends one). Sessions scored as automated are excluded and counted separately in `excludedAutomated` rather than dropped silently. `unknownSessions` were looked up and could not be placed; `notRecordedSessions` predate derivation and were never looked up at all — the two are reported apart because they are different claims. Rendering this data requires crediting DB-IP (CC BY 4.0); the string is returned in `attribution` so a client cannot forget it. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"range","required":false,"description":"Calendar window in the project's reporting timezone: '7d', '30d', '90d' or 'all' (default 30d). Unknown values are a 400 invalid_range — never a silent fallback."},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"Custom window start (ISO date, cut at midnight in the project timezone; overrides range). Must be within the plan's retention window or the request 403s with range_out_of_retention."},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"Custom window end (ISO date, inclusive day; defaults to today)."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["rows","placedSessions","unknownSessions","notRecordedSessions","excludedAutomated","attribution"],"properties":{"rows":{"type":"array","items":{"type":"object","required":["country","sessions","conversions","conversionRate"],"properties":{"country":{"type":"string","description":"ISO 3166-1 alpha-2"},"sessions":{"type":"number"},"conversions":{"type":"number"},"conversionRate":{"type":"number","description":"Null below the 30-session display floor — not zero.","nullable":true}}}},"placedSessions":{"type":"number"},"unknownSessions":{"type":"number"},"notRecordedSessions":{"type":"number"},"excludedAutomated":{"type":"number"},"attribution":{"type":"string"},"window":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/scans/{id}":{"get":{"operationId":"getMgmtScansById","summary":"Full first-impression scan report","tags":["mgmt"],"description":"Full findings, adaptive-candidate targets, and any generated persona suggestions. The first authenticated read claims an unclaimed scan for this user; scans claimed by another user are not found. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Scan id."}],"responses":{"200":{"description":"Full scan report.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Full scan report."}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/scans/{id}/suggestions":{"post":{"operationId":"postMgmtScansByIdSuggestions","summary":"Generate persona adaptation suggestions for a scan","tags":["mgmt"],"description":"One LLM generation per scan, cached into the scan results. Per-user daily limit. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Scan id."}],"responses":{"200":{"description":"Generated (or cached) persona suggestions.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"suggestions":{"type":"array","items":{"type":"object","additionalProperties":true}}},"description":"Generated (or cached) persona suggestions."}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/scans/{id}/link":{"post":{"operationId":"postMgmtScansByIdLink","summary":"Link a scan to a created project","tags":["mgmt"],"description":"Records which project came out of a scan. Only the scan claimant can link. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId"],"properties":{"projectId":{"type":"string","format":"uuid"}}}}}},"security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Scan id."}],"responses":{"200":{"description":"Linked.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"description":"Linked."}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/guardrails/{componentId}/unpause":{"post":{"operationId":"postMgmtProjectsByIdGuardrailsByComponentIdUnpause","summary":"Unpause guardrail-paused variants for a component","tags":["mgmt"],"description":"Unpause guardrail-paused variants for a component. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["variantIds"],"description":"The variants to unpause for this component.","properties":{"variantIds":{"type":"array","description":"Variant ids to clear the paused state on. Must be non-empty.","items":{"type":"string"}}},"additionalProperties":true}}},"description":"The variants to unpause for this component."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."},{"schema":{"type":"string"},"in":"path","name":"componentId","required":true,"description":"Component identifier the guardrail paused variants on."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/pooling-readiness":{"get":{"operationId":"getMgmtProjectsByIdPoolingReadiness","summary":"Replay-based readiness check for persona-pooled serving","tags":["mgmt"],"description":"Replay-based readiness check for persona-pooled serving. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Replay report (see domain/replay-sim.ts) plus the derived verdict.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Current projects.pooled_serving value."},"decisions":{"type":"number"},"agreementRate":{"type":"number"},"verdict":{"type":"string","description":"'ready' | 'not_ready' | 'insufficient_data'"},"truncated":{"type":"boolean","description":"True when the replay hit the 50k most-recent-exposures cap."}},"additionalProperties":true,"description":"Replay report (see domain/replay-sim.ts) plus the derived verdict."}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/pooling":{"post":{"operationId":"postMgmtProjectsByIdPooling","summary":"Enable or disable persona-pooled serving","tags":["mgmt"],"description":"Enable or disable persona-pooled serving. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enabled"],"description":"The new pooled_serving value. Enabling requires a fresh, conclusive, non-negative replay report for the running policy version on every path with traffic — variant (`pooling`) and slot (`slots`) — or 409 replay_required. Disabling is the one-click rollback and is always allowed.","properties":{"enabled":{"type":"boolean","description":"true to serve from the persona × segment hierarchy."},"override":{"type":"object","description":"Platform-admin-only (dashboard session): enable without a passing replay report. `reason` (10–500 characters) is required and is written to the audit log before the flag changes.","properties":{"reason":{"type":"string"}}}},"additionalProperties":true}}},"description":"The new pooled_serving value. Enabling requires a fresh, conclusive, non-negative replay report for the running policy version on every path with traffic — variant (`pooling`) and slot (`slots`) — or 409 replay_required. Disabling is the one-click rollback and is always allowed."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"enabled":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/layout-readiness":{"get":{"operationId":"getMgmtProjectsByIdLayoutReadiness","summary":"Replay-based readiness check for the factored layout model","tags":["mgmt"],"description":"Replay-based readiness check for the factored layout model. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Replay report (see domain/layout-replay-sim.ts) plus the derived verdict.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Current settings.factored_layout value."},"decisions":{"type":"number"},"verdict":{"type":"string","description":"'ready' | 'not_ready' | 'insufficient_data'"},"truncated":{"type":"boolean","description":"True when the replay hit the most-recent-decisions cap."},"sectionSets":{"type":"number","description":"Distinct section sets in the history; the largest one is replayed."}},"additionalProperties":true,"description":"Replay report (see domain/layout-replay-sim.ts) plus the derived verdict."}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/layout-model":{"post":{"operationId":"postMgmtProjectsByIdLayoutModel","summary":"Enable or disable the factored layout model","tags":["mgmt"],"description":"Enable or disable the factored layout model. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enabled"],"description":"The new settings.factored_layout value. Enabling requires a fresh, conclusive, non-negative layout replay report for the running policy version (409 replay_required otherwise). Disabling is the one-click rollback and is always allowed.","properties":{"enabled":{"type":"boolean","description":"true to serve layouts from the factored (parent × position) model."},"override":{"type":"object","description":"Platform-admin-only (dashboard session): enable without a passing replay report. `reason` (10–500 characters) is required and is written to the audit log before the flag changes.","properties":{"reason":{"type":"string"}}}},"additionalProperties":true}}},"description":"The new settings.factored_layout value. Enabling requires a fresh, conclusive, non-negative layout replay report for the running policy version (409 replay_required otherwise). Disabling is the one-click rollback and is always allowed."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"enabled":{"type":"boolean"}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-readiness":{"get":{"operationId":"getMgmtProjectsByIdSlotReadiness","summary":"Replay-based readiness check for the factored slot model","tags":["mgmt"],"description":"Replays factored-vs-legacy slot serving over this project's own recent decisions. Read `conclusive`, not `delta` — a replayed bandit is biased in its own favour and the harness measures that bias against a permutation null. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Per-slot replay reports and a verdict.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Per-slot replay reports and a verdict."}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/slot-model":{"post":{"operationId":"postMgmtProjectsByIdSlotModel","summary":"Enable or disable the factored slot model","tags":["mgmt"],"description":"Enabling requires a fresh, conclusive, non-negative `slot_model` replay report for the running policy version (409 replay_required otherwise) and EV serving off (409 ev_serving_active). Disabling is always allowed. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enabled"],"properties":{"enabled":{"type":"boolean"},"override":{"type":"object","description":"Platform-admin-only (dashboard session): enable without a passing replay report. `reason` (10–500 characters) is required and is written to the audit log before the flag changes.","properties":{"reason":{"type":"string"}}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Flag written.","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Flag written."}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/labels-diff":{"get":{"operationId":"getMgmtProjectsByIdLabelsDiff","summary":"What a promotion of the shipped classifier version would change","tags":["mgmt"],"description":"What a promotion of the shipped classifier version would change. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"shippedVersion":{"type":"string"},"promotedVersion":{"type":"string","nullable":true},"previousVersion":{"type":"string","nullable":true},"upToDate":{"type":"boolean","description":"True when the project already serves the shipped version."},"shadowRows":{"type":"number","description":"Sections with a pending shadow label."},"parentChanged":{"type":"number","description":"Sections whose ordering-relevant parent type would change."},"roleChanged":{"type":"number"},"changes":{"type":"array","description":"Up to 200 changed sections, parent changes first."}},"additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/labels-promotion":{"post":{"operationId":"postMgmtProjectsByIdLabelsPromotion","summary":"Promote the shadow labels, or roll a promotion back","tags":["mgmt"],"description":"Promote the shadow labels, or roll a promotion back. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"description":"Both directions are the same atomic swap; 'rollback' restores the labels the last promotion replaced.","properties":{"action":{"type":"string","enum":["promote","rollback"]}},"additionalProperties":true}}},"description":"Both directions are the same atomic swap; 'rollback' restores the labels the last promotion replaced."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project UUID."}],"security":[{"secretKey":[]}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"action":{"type":"string"},"swappedRows":{"type":"number"},"promotedVersion":{"type":"string","nullable":true}},"additionalProperties":true}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/audience-evidence":{"get":{"operationId":"getMgmtProjectsByIdAudienceEvidence","summary":"Per-audience serving status and evidence verdict, per variant","tags":["mgmt"],"description":"Per-audience serving status and evidence verdict, per variant. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Audience rows carrying BOTH the serving status (learning/independent) and the evidence verdict (same states as the Components screen), from the same cells the evidence report reads","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Audience rows carrying BOTH the serving status (learning/independent) and the evidence verdict (same states as the Components screen), from the same cells the evidence report reads"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/report-shares":{"get":{"operationId":"getMgmtProjectsByIdReportShares","summary":"List shared lift-report links","tags":["mgmt"],"description":"Links to the read-only lift report for this project, newest first. Active links plus those revoked or expired in the last 7 days. Admin role required. The token is never returned after creation. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"shares":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string","nullable":true},"createdBy":{"type":"string"},"createdAt":{"type":"string"},"expiresAt":{"type":"string"},"revokedAt":{"type":"string","nullable":true},"snapshotComputedAt":{"type":"string"},"status":{"type":"string","enum":["active","expired","revoked"]}}}}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"postMgmtProjectsByIdReportShares","summary":"Create a shared lift-report link","tags":["mgmt"],"description":"Snapshots the project's holdout lift (the same computation as the Home card) and returns a signed, read-only link to it. The token appears in this response only — store the URL; it cannot be retrieved later. Expires after `expiresInDays` (default 30, max 180). At most 25 active links per project. Admin role required. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"expiresInDays":{"type":"integer","minimum":1,"maximum":180,"description":"Days until the link stops working."},"label":{"type":"string","maxLength":80,"description":"Your own note to tell links apart. Not shown to the reader."}}}}}},"security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."}],"responses":{"201":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"share":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string","nullable":true},"createdBy":{"type":"string"},"createdAt":{"type":"string"},"expiresAt":{"type":"string"},"revokedAt":{"type":"string","nullable":true},"snapshotComputedAt":{"type":"string"},"status":{"type":"string","enum":["active","expired","revoked"]}}},"token":{"type":"string","description":"The raw link token. Returned once."},"url":{"type":"string","description":"The public report URL. Returned once."}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/report-shares/{shareId}/refresh":{"post":{"operationId":"postMgmtProjectsByIdReportSharesByShareIdRefresh","summary":"Refresh a shared lift-report snapshot","tags":["mgmt"],"description":"Recomputes the snapshot behind an active link so it shows the current result. The URL does not change. Revoked or expired links cannot be refreshed. Admin role required. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."},{"schema":{"type":"string"},"in":"path","name":"shareId","required":true,"description":"Share id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"share":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string","nullable":true},"createdBy":{"type":"string"},"createdAt":{"type":"string"},"expiresAt":{"type":"string"},"revokedAt":{"type":"string","nullable":true},"snapshotComputedAt":{"type":"string"},"status":{"type":"string","enum":["active","expired","revoked"]}}}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mgmt/projects/{id}/report-shares/{shareId}":{"delete":{"operationId":"deleteMgmtProjectsByIdReportSharesByShareId","summary":"Revoke a shared lift-report link","tags":["mgmt"],"description":"The link stops working immediately. Idempotent. Admin role required. Authenticate with a secret key (`Authorization: Bearer sk_…`) or a dashboard session token, scoped to a project you can access. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`; a `429` also sets `Retry-After`.","security":[{"secretKey":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project id."},{"schema":{"type":"string"},"in":"path","name":"shareId","required":true,"description":"Share id."}],"responses":{"200":{"description":"Default Response","headers":{"RateLimit-Limit":{"schema":{"schema":{"type":"integer"}},"description":"Request quota for the current window."},"RateLimit-Remaining":{"schema":{"schema":{"type":"integer"}},"description":"Requests remaining in the current window."},"RateLimit-Reset":{"schema":{"schema":{"type":"integer"}},"description":"Unix epoch seconds when the current window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"share":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string","nullable":true},"createdBy":{"type":"string"},"createdAt":{"type":"string"},"expiresAt":{"type":"string"},"revokedAt":{"type":"string","nullable":true},"snapshotComputedAt":{"type":"string"},"status":{"type":"string","enum":["active","expired","revoked"]}}}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"servers":[{"url":"https://api.sentient-ui.com","description":"Production"}],"tags":[{"name":"ingest","description":"SDK event ingest and assignment (pk_ authenticated)"},{"name":"mgmt","description":"Project management (sk_ or dashboard session)"},{"name":"agent","description":"AI agent content access (sk_ authenticated)"},{"name":"editor","description":"On-site visual editor (short-lived editor token)"},{"name":"public","description":"Unauthenticated endpoints"},{"name":"infra","description":"Health, discovery, and transport endpoints — not part of the versioned API"}]}