{"openapi":"3.1.0","info":{"title":"SignalMonitor API","version":"0.1.0","description":"Self-hosted telemetry API for product events, errors, breadcrumbs, browser click maps, privacy-safe session replays, LLM calls, traces, spans, Web Vitals, source maps, and operator workflows.\n\n## Integration guide\n\nFor TypeScript, Node.js, browser, and Next.js projects, use the official `@sigmon/sdk` package when it is available in your package registry or vendored workspace. The SDK is the recommended path for complete integrations because it keeps browser and server entrypoints separate, maps payloads consistently, provides Next.js route/action wrappers, and exposes identify helpers for user and tenant traits.\n\nRaw HTTP remains the stable contract for other languages, automation, and direct integrations. All ingestion requests use project/environment-scoped API keys created in the SignalMonitor console.\n\n## Recommended rollout\n\n1. Create one SignalMonitor project and one environment per deployed app environment.\n2. Create separate ingestion keys for server and browser telemetry.\n3. Use server-only variables such as `SIGMON_ENDPOINT` and `SIGMON_API_KEY` for API routes, workers, server actions, and scheduled jobs.\n4. Use browser variables such as `NEXT_PUBLIC_SIGMON_ENDPOINT` and `NEXT_PUBLIC_SIGMON_BROWSER_KEY` only with a browser-scoped ingestion key.\n5. Send `identifyUser` / `POST /v1/identify/user` after login or session load, and `identifyTenant` / `POST /v1/identify/tenant` after tenant/workspace selection.\n6. Send events, errors, breadcrumbs, click maps, privacy-safe session replays, traces, spans, Web Vitals, experiment exposures, and LLM calls with stable `tenant_id`, `user_id`, `session_id`, `trace_id`, `source`, and `release` fields when available.\n7. Upload source maps from CI for minified browser bundles so production stacks can be resolved.\n\n## Key model\n\nBrowser ingestion keys are public by design, but they must be scoped to one project and environment. Server ingestion keys and source-map upload tokens must stay in server or CI secret storage."},"servers":[{"url":"https://my.sigmon.app","description":"Production"}],"tags":[{"name":"Health","description":"Public service health and readiness checks."},{"name":"Ingestion","description":"API-key authenticated telemetry ingestion endpoints. These endpoints are safe to call from SDKs or raw HTTP clients as long as the API key is scoped to the intended project/environment."},{"name":"Source maps","description":"CI source-map uploads with dedicated source-map upload tokens."},{"name":"Auth","description":"Human session login and session management."},{"name":"Session authenticated","description":"Admin, query, alert, and system routes that require a human session cookie."}],"externalDocs":{"description":"Raw OpenAPI document","url":"/openapi.json"},"components":{"securitySchemes":{"ingestionApiKey":{"type":"http","scheme":"bearer","bearerFormat":"SignalMonitor ingestion API key","description":"Project/environment scoped ingestion key, for example `sh_...`."},"sourceMapUploadToken":{"type":"http","scheme":"bearer","bearerFormat":"SignalMonitor source-map upload token","description":"CI-only source-map upload token created from the Artifacts console."},"heartbeatSecret":{"type":"http","scheme":"bearer","bearerFormat":"SignalMonitor heartbeat monitor secret","description":"One-time heartbeat monitor secret returned when creating a heartbeat monitor."},"sessionCookie":{"type":"apiKey","in":"cookie","name":"__Host-sigmon_session","description":"Production human session cookie set by `/auth/login`."},"readToken":{"type":"http","scheme":"bearer","bearerFormat":"SignalMonitor read token","description":"Project/environment scoped, read-only, revocable credential, for example `shread_...`. Accepted as an alternative to the session cookie on `/query/*` read routes only; it cannot access fleet routes or perform any mutation."}},"schemas":{"AnalyticsSegmentLeafValue":{"oneOf":[{"type":"string","maxLength":1024},{"type":"number"},{"type":"boolean"},{"type":"array","maxItems":64,"items":{"type":"string","maxLength":1024}}]},"AnalyticsSegmentPropertyCondition":{"type":"object","required":["name","operator"],"additionalProperties":false,"properties":{"name":{"type":"string","pattern":"^[A-Za-z0-9_.:-]{1,64}$"},"operator":{"type":"string","enum":["eq","neq","contains","gt","gte","lt","lte","in","exists"]},"value":{"$ref":"#/components/schemas/AnalyticsSegmentLeafValue"}}},"AnalyticsSegmentGroupNode":{"type":"object","required":["kind","op","children"],"additionalProperties":false,"properties":{"kind":{"type":"string","const":"group"},"op":{"type":"string","enum":["and","or","not"]},"children":{"type":"array","minItems":1,"maxItems":8,"items":{"$ref":"#/components/schemas/AnalyticsSegmentNode"}}},"allOf":[{"if":{"properties":{"op":{"const":"not"}},"required":["op"]},"then":{"properties":{"children":{"maxItems":1}}}}]},"AnalyticsSegmentEventNode":{"type":"object","required":["kind"],"additionalProperties":false,"properties":{"kind":{"type":"string","const":"event"},"eventName":{"type":"string","minLength":1,"maxLength":256},"property":{"$ref":"#/components/schemas/AnalyticsSegmentPropertyCondition"},"frequency":{"type":"object","required":["operator","count"],"additionalProperties":false,"properties":{"operator":{"type":"string","enum":["gte","lte","eq"]},"count":{"type":"integer","minimum":0}}},"recency":{"type":"object","required":["withinDays"],"additionalProperties":false,"properties":{"withinDays":{"type":"integer","minimum":1,"maximum":3650}}}}},"AnalyticsSegmentTraitNode":{"type":"object","required":["kind","source","name","operator"],"additionalProperties":false,"properties":{"kind":{"type":"string","const":"trait"},"source":{"type":"string","enum":["user","tenant"]},"name":{"type":"string","pattern":"^[A-Za-z0-9_.:-]{1,64}$"},"operator":{"type":"string","enum":["eq","neq","contains","gt","gte","lt","lte","in","exists"]},"value":{"$ref":"#/components/schemas/AnalyticsSegmentLeafValue"}}},"AnalyticsSegmentNode":{"description":"Recursive analytics segment expression. Definitions are limited to 32 nodes and depth 5.","oneOf":[{"$ref":"#/components/schemas/AnalyticsSegmentGroupNode"},{"$ref":"#/components/schemas/AnalyticsSegmentEventNode"},{"$ref":"#/components/schemas/AnalyticsSegmentTraitNode"}]},"AcceptedResponse":{"type":"object","required":["accepted","id"],"properties":{"accepted":{"type":"boolean","const":true},"id":{"type":"string","description":"Generated telemetry signal id."}}},"IdentifyAcceptedResponse":{"type":"object","required":["accepted"],"properties":{"accepted":{"type":"boolean","const":true}}},"AnalyticsInsightInput":{"type":"object","required":["projectId","environmentId","name","definition"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":256},"description":{"type":["string","null"],"maxLength":1024},"definition":{"type":"object","required":["bucket","metric"],"properties":{"bucket":{"type":"string","enum":["hour","day"]},"metric":{"type":"string","enum":["count","unique_actors"]},"eventName":{"type":"string"},"breakdownProperty":{"type":"string"},"filters":{"type":"array","items":{"type":"object"},"maxItems":12}}}}},"AnalyticsInsightPatch":{"type":"object","minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":256},"description":{"type":["string","null"],"maxLength":1024},"definition":{"$ref":"#/components/schemas/AnalyticsInsightInput/properties/definition"}}},"PromotedEventPropertyInput":{"type":"object","required":["projectId","environmentId","property"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"property":{"type":"string","pattern":"^[A-Za-z0-9_.:-]{1,64}$"},"displayName":{"type":"string","maxLength":80}}},"AnalyticsDashboardInput":{"type":"object","required":["projectId","environmentId","name","widgets"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":256},"description":{"type":["string","null"],"maxLength":1024},"category":{"type":"string","enum":["executive","operational","product"],"default":"operational"},"filters":{"type":"object","additionalProperties":false,"properties":{"window":{"type":"string","enum":["24h","7d","30d"],"default":"7d"}}},"widgets":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"object","required":["type","title"],"properties":{"id":{"type":"string"},"type":{"type":"string","enum":["metric.events","metric.errors","top.events","trend.events","trend.errors","insight"]},"title":{"type":"string","minLength":1,"maxLength":120},"width":{"type":"string","enum":["half","full"],"default":"half"},"options":{"type":"object","additionalProperties":true}}}}}},"AnalyticsDashboardPatch":{"type":"object","minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":256},"description":{"type":["string","null"],"maxLength":1024},"category":{"type":"string","enum":["executive","operational","product"]},"filters":{"type":"object","additionalProperties":false,"properties":{"window":{"type":"string","enum":["24h","7d","30d"]}}},"widgets":{"$ref":"#/components/schemas/AnalyticsDashboardInput/properties/widgets"}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"requiredRole":{"type":"string","enum":["viewer","member","admin"],"description":"Present on `role_required` 403 responses: the minimum console role the operation needs."},"hint":{"type":"string","description":"Optional actionable setup guidance returned by ingestion endpoints for common integration failures."}}},"SurveyQuestion":{"type":"object","required":["id","type","label","required"],"properties":{"id":{"type":"string","examples":["satisfaction"]},"type":{"type":"string","enum":["rating","choice","text"]},"label":{"type":"string","examples":["How satisfied are you with this workflow?"]},"required":{"type":"boolean","default":true},"scale":{"type":"object","properties":{"min":{"type":"integer","examples":[1]},"max":{"type":"integer","examples":[5]},"minLabel":{"type":"string","examples":["Hard"]},"maxLabel":{"type":"string","examples":["Great"]}}},"options":{"type":"array","items":{"type":"string"}}}},"Survey":{"type":"object","required":["id","projectId","environmentId","key","name","status","actorType","questions","targeting"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"key":{"type":"string","examples":["activation_pulse"]},"name":{"type":"string","examples":["Activation pulse"]},"description":{"type":["string","null"]},"status":{"type":"string","enum":["draft","active","paused","archived"]},"actorType":{"type":"string","enum":["user","tenant","session"]},"triggerEvent":{"type":["string","null"],"examples":["checkout.completed"]},"questions":{"type":"array","items":{"$ref":"#/components/schemas/SurveyQuestion"}},"targeting":{"type":"object","properties":{"segmentId":{"type":"string"},"userId":{"type":"string"},"tenantId":{"type":"string"},"eventName":{"type":"string"},"sampleRate":{"type":"number","minimum":0,"maximum":1}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":["string","null"],"format":"date-time"}}},"SurveyResponsePayload":{"type":"object","required":["survey_id","answers"],"properties":{"survey_id":{"type":"string","examples":["srv_123"]},"actor_type":{"type":"string","enum":["user","tenant","session","anonymous"],"default":"user"},"actor_id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"session_id":{"type":"string"},"trace_id":{"type":"string"},"source":{"type":"string","examples":["web"]},"release":{"type":"string","examples":["2026.06.01"]},"answers":{"type":"object","description":"Question id to answer value map. Secrets should not be sent.","additionalProperties":true,"examples":[{"satisfaction":5,"comment":"Great"}]},"metadata":{"type":"object","additionalProperties":true},"timestamp":{"type":"string","format":"date-time"}}},"FeedbackPayload":{"type":"object","required":["message"],"properties":{"message":{"type":"string","examples":["The export button is confusing."]},"category":{"type":"string","examples":["ux"]},"page_url":{"type":"string","format":"uri","examples":["https://app.example.com/reports"]},"path":{"type":"string","examples":["/reports?tab=exports"]},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"session_id":{"type":"string"},"trace_id":{"type":"string"},"source":{"type":"string","examples":["browser"]},"release":{"type":"string","examples":["2026.06.01"]},"user_agent":{"type":"string"},"replay_id":{"type":"string","description":"Active session replay id, so the console can link the report to the replay. Nothing new is recorded."},"snapshot":{"type":"object","description":"Optional masked DOM snapshot (not a pixel screenshot) captured by the SDK only when the host app opts in with `captureSnapshot`. The SDK masks inputs, `[data-sigmon-mask]` subtrees and (optionally) all text before sending; the API re-sanitises it with an allowlist (no scripts, handlers, frames, or external URLs) and stores it on local disk. Stored only when the environment has `allowScreenshot` enabled, within a low per-key snapshot rate limit and a per-project disk quota; otherwise it is dropped and the text report is still accepted. This route accepts bodies up to 2 MiB; every other ingestion route keeps the 1 MiB default.","required":["html"],"properties":{"html":{"type":"string","maxLength":1000000},"viewport":{"type":"object","properties":{"width":{"type":"integer"},"height":{"type":"integer"}}},"scroll":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}}},"truncated":{"type":"boolean"},"mask_all_text":{"type":"boolean"}}},"metadata":{"type":"object","additionalProperties":true},"timestamp":{"type":"string","format":"date-time"}}},"FeedbackWidgetSettings":{"type":"object","required":["projectId","environmentId","enabled","title","prompt","placeholder","buttonLabel","accentColor","allowScreenshot"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"enabled":{"type":"boolean"},"title":{"type":"string"},"prompt":{"type":"string"},"placeholder":{"type":"string"},"buttonLabel":{"type":"string"},"accentColor":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"allowScreenshot":{"type":"boolean","description":"Server-side switch for masked page snapshots (default false). When off, `snapshot` payloads are dropped and ingestion returns `snapshot_stored: false`. The host app must also opt in with `captureSnapshot` in the SDK."},"privacyNote":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"FeedbackItem":{"type":"object","required":["id","projectId","environmentId","status","message","metadata","submittedAt","receivedAt","updatedAt"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"status":{"type":"string","enum":["open","in_progress","reviewed","resolved","archived"]},"priority":{"type":["string","null"],"enum":["low","medium","high","urgent",null]},"assigneeUserId":{"type":["string","null"],"description":"Console user id the item is assigned to."},"tags":{"type":"array","items":{"type":"string"},"maxItems":10},"replayId":{"type":["string","null"],"description":"Session replay recorded while the report was sent, when the SDK had one active."},"snapshot":{"type":["object","null"],"description":"Summary of the stored masked DOM snapshot; fetch the sanitised markup from GET /query/feedback/{id}/snapshot.","properties":{"bytes":{"type":"integer"},"viewport":{"type":["object","null"],"properties":{"width":{"type":"integer"},"height":{"type":"integer"}}},"scroll":{"type":["object","null"],"properties":{"x":{"type":"number"},"y":{"type":"number"}}},"truncated":{"type":"boolean"},"maskAllText":{"type":"boolean"}}},"message":{"type":"string"},"category":{"type":["string","null"]},"pageUrl":{"type":["string","null"]},"path":{"type":["string","null"]},"tenantId":{"type":["string","null"]},"userId":{"type":["string","null"]},"sessionId":{"type":["string","null"]},"traceId":{"type":["string","null"]},"release":{"type":["string","null"]},"source":{"type":["string","null"]},"userAgent":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":true},"submittedAt":{"type":"string","format":"date-time"},"receivedAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"SurveyResults":{"type":"object","required":["survey","window","totals","questions","recentResponses"],"properties":{"survey":{"$ref":"#/components/schemas/Survey"},"window":{"type":"string","enum":["24h","7d","30d"]},"totals":{"type":"object","required":["responses","users","tenants","sessions"],"properties":{"responses":{"type":"integer"},"users":{"type":"integer"},"tenants":{"type":"integer"},"sessions":{"type":"integer"}}},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["rating","choice","text"]},"responses":{"type":"integer"},"average":{"type":"number"},"choices":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"count":{"type":"integer"}}}}}}},"recentResponses":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"surveyId":{"type":"string"},"actorType":{"type":"string","enum":["user","tenant","session","anonymous"]},"actorId":{"type":["string","null"]},"tenantId":{"type":["string","null"]},"userId":{"type":["string","null"]},"sessionId":{"type":["string","null"]},"answers":{"type":"object","additionalProperties":true},"submittedAt":{"type":"string","format":"date-time"}}}}}},"MessageCampaign":{"type":"object","required":["id","projectId","environmentId","key","name","status","channelType","body","consentCategory"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"key":{"type":"string","examples":["invoice_activation"]},"name":{"type":"string","examples":["Invoice activation"]},"description":{"type":["string","null"]},"status":{"type":"string","enum":["draft","active","paused","archived"]},"channelType":{"type":"string","enum":["email","webhook","in_app"]},"notificationChannelId":{"type":["string","null"],"description":"Required for email and webhook campaigns."},"segmentId":{"type":["string","null"],"description":"Optional analytics segment id for the target audience."},"conversionEvent":{"type":["string","null"],"examples":["invoice.paid"]},"subject":{"type":["string","null"]},"body":{"type":"string"},"ctaUrl":{"type":["string","null"],"format":"uri"},"consentCategory":{"type":"string","examples":["product"]},"privacyNote":{"type":["string","null"]},"deliveryEnabled":{"type":"boolean","description":"True when Sigmon delivers the campaign itself (Pro, `campaign_delivery`); false keeps it measurement-only."},"audienceType":{"type":"string","enum":["segment","all_identified"],"description":"`segment` targets the users of `segmentId` (a user segment); `all_identified` targets every identified user."},"deliveryState":{"type":"string","enum":["none","scheduled","sending","completed","cancelled"]},"scheduledAt":{"type":["string","null"],"format":"date-time"},"deliveryStartedAt":{"type":["string","null"],"format":"date-time"},"deliveryCompletedAt":{"type":["string","null"],"format":"date-time"},"perUserCap":{"type":"integer","minimum":1,"maximum":100,"description":"Most times one user is shown an in-app campaign. E-mail is always sent once per user."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":["string","null"],"format":"date-time"}}},"MessageCampaignPreview":{"type":"object","required":["channel","subject","text","html","recipient","missingVariables"],"properties":{"channel":{"type":"string","enum":["email","in_app"]},"subject":{"type":"string"},"text":{"type":"string"},"html":{"type":["string","null"],"description":"HTML-escaped e-mail body; null for in-app."},"recipient":{"type":["object","null"],"description":"The profile rendered for; null when sample data was used.","properties":{"userId":{"type":"string"},"email":{"type":["string","null"]}}},"missingVariables":{"type":"array","items":{"type":"string"}}}},"CampaignEventPayload":{"type":"object","required":["campaign_id","type"],"properties":{"campaign_id":{"type":"string"},"type":{"type":"string","enum":["delivered","opened","clicked","dismissed","converted"]},"user_id":{"type":"string"},"anonymous_id":{"type":"string"},"tenant_id":{"type":"string"},"session_id":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"source":{"type":"string"},"release":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}},"MessageCampaignDeliveryCounts":{"type":"object","required":["pending","sending","sent","failed","skipped","total"],"properties":{"pending":{"type":"integer"},"sending":{"type":"integer"},"sent":{"type":"integer"},"failed":{"type":"integer"},"skipped":{"type":"integer","description":"Opted out, over the daily cap, no e-mail address, or cancelled."},"total":{"type":"integer"}}},"MessageCampaignResults":{"type":"object","required":["campaign","window","totals","rates","recentEvents","optOuts"],"properties":{"campaign":{"$ref":"#/components/schemas/MessageCampaign"},"window":{"type":"string","enum":["24h","7d","30d"]},"totals":{"type":"object","required":["queued","sent","delivered","opened","clicked","converted","failed","optedOut","uniqueActors"],"properties":{"queued":{"type":"integer"},"sent":{"type":"integer"},"delivered":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"},"converted":{"type":"integer"},"failed":{"type":"integer"},"optedOut":{"type":"integer"},"dismissed":{"type":"integer"},"uniqueActors":{"type":"integer"}}},"deliveries":{"type":"object","description":"Per-recipient delivery state of a delivery campaign, per channel. All zero for measurement-only campaigns.","properties":{"email":{"$ref":"#/components/schemas/MessageCampaignDeliveryCounts"},"in_app":{"$ref":"#/components/schemas/MessageCampaignDeliveryCounts"}}},"rates":{"type":"object","required":["deliveryRate","openRate","clickRate","conversionRate","optOutRate"],"properties":{"deliveryRate":{"type":"number"},"openRate":{"type":"number"},"clickRate":{"type":"number"},"conversionRate":{"type":"number"},"optOutRate":{"type":"number"}}},"recentEvents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"campaignId":{"type":"string"},"type":{"type":"string","enum":["queued","sent","delivered","opened","clicked","converted","failed","opted_out","dismissed"]},"actorType":{"type":"string","enum":["user","tenant","session","anonymous"]},"actorId":{"type":["string","null"]},"tenantId":{"type":["string","null"]},"userId":{"type":["string","null"]},"occurredAt":{"type":"string","format":"date-time"}}}},"optOuts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"actorType":{"type":"string","enum":["user","tenant","session","anonymous"]},"actorId":{"type":"string"},"category":{"type":"string"},"reason":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}}}}},"NpsSegmentSummary":{"type":"object","required":["key","label","responses","score","promoters","passives","detractors"],"properties":{"key":{"type":"string"},"label":{"type":"string"},"responses":{"type":"integer"},"score":{"type":"integer","minimum":-100,"maximum":100},"promoters":{"type":"integer"},"passives":{"type":"integer"},"detractors":{"type":"integer"}}},"NpsResults":{"type":"object","required":["survey","window","questionId","totals","trend","segments","recentResponses"],"properties":{"survey":{"$ref":"#/components/schemas/Survey"},"window":{"type":"string","enum":["24h","7d","30d"]},"questionId":{"type":"string"},"totals":{"type":"object","required":["responses","promoters","passives","detractors","score","average"],"properties":{"responses":{"type":"integer"},"promoters":{"type":"integer"},"passives":{"type":"integer"},"detractors":{"type":"integer"},"score":{"type":"integer","minimum":-100,"maximum":100},"average":{"type":["number","null"]}}},"trend":{"type":"array","items":{"type":"object","required":["bucket","responses","score","promoters","passives","detractors"],"properties":{"bucket":{"type":"string","examples":["2026-05-01"]},"responses":{"type":"integer"},"score":{"type":"integer","minimum":-100,"maximum":100},"promoters":{"type":"integer"},"passives":{"type":"integer"},"detractors":{"type":"integer"}}}},"segments":{"type":"object","required":["tenants","releases","plans"],"properties":{"tenants":{"type":"array","items":{"$ref":"#/components/schemas/NpsSegmentSummary"}},"releases":{"type":"array","items":{"$ref":"#/components/schemas/NpsSegmentSummary"}},"plans":{"type":"array","items":{"$ref":"#/components/schemas/NpsSegmentSummary"}}}},"recentResponses":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"surveyId":{"type":"string"},"actorType":{"type":"string","enum":["user","tenant","session","anonymous"]},"actorId":{"type":["string","null"]},"tenantId":{"type":["string","null"]},"userId":{"type":["string","null"]},"sessionId":{"type":["string","null"]},"answers":{"type":"object","additionalProperties":true},"submittedAt":{"type":"string","format":"date-time"}}}}}},"FeatureFlagVariant":{"type":"object","required":["key","value"],"properties":{"key":{"type":"string","examples":["off","on"]},"value":{"oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"},{"type":"null"}]}}},"FeatureFlagRule":{"type":"object","required":["variant"],"properties":{"id":{"type":"string"},"description":{"type":"string"},"variant":{"type":"string","examples":["on"]},"match":{"type":"object","properties":{"userId":{"type":"string"},"tenantId":{"type":"string"},"sessionId":{"type":"string"},"traits":{"type":"object","additionalProperties":true}}},"rollout":{"type":"object","description":"Optional deterministic percentage rollout applied after match conditions pass.","required":["percentage","stickiness"],"properties":{"percentage":{"type":"number","minimum":0,"maximum":100,"examples":[10]},"stickiness":{"type":"string","enum":["user","tenant","session"],"examples":["user"]},"salt":{"type":"string"}}}}},"FeatureFlag":{"type":"object","required":["id","projectId","environmentId","key","name","status","defaultVariant","variants","rules"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"key":{"type":"string","examples":["new_checkout"]},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["draft","active","paused","archived"]},"defaultVariant":{"type":"string","examples":["off"]},"variants":{"type":"array","items":{"$ref":"#/components/schemas/FeatureFlagVariant"}},"rules":{"type":"array","items":{"$ref":"#/components/schemas/FeatureFlagRule"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":["string","null"],"format":"date-time"}}},"FeatureFlagAudit":{"type":"object","required":["id","featureFlagId","projectId","environmentId","action","changes","createdAt"],"properties":{"id":{"type":"string"},"featureFlagId":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"action":{"type":"string","enum":["created","updated","archived"]},"actorId":{"type":["string","null"]},"changes":{"type":"object","additionalProperties":true},"createdAt":{"type":"string","format":"date-time"}}},"FeatureFlagEvaluation":{"type":"object","required":["key","variant","value","reason","matched"],"properties":{"key":{"type":"string","examples":["new_checkout"]},"variant":{"type":"string","examples":["on"]},"value":{"oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"},{"type":"null"}]},"reason":{"type":"string","enum":["rule_match","default","missing","inactive"]},"matched":{"type":"boolean"},"ruleId":{"type":"string"}}},"BetaProgram":{"type":"object","required":["id","projectId","environmentId","key","name","status","actorType","featureFlagVariant"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"key":{"type":"string","examples":["checkout_beta"]},"name":{"type":"string","examples":["Checkout beta"]},"description":{"type":["string","null"]},"status":{"type":"string","enum":["draft","active","paused","archived"]},"actorType":{"type":"string","enum":["user","tenant"]},"featureFlagId":{"type":["string","null"],"description":"Optional linked flag. Active participants are synced as targeting rules."},"featureFlagVariant":{"type":"string","examples":["on"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":["string","null"],"format":"date-time"}}},"BetaProgramParticipant":{"type":"object","required":["id","programId","projectId","environmentId","actorType","actorId","status"],"properties":{"id":{"type":"string"},"programId":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"actorType":{"type":"string","enum":["user","tenant"]},"actorId":{"type":"string"},"status":{"type":"string","enum":["invited","active","opted_out","removed"]},"notes":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"removedAt":{"type":["string","null"],"format":"date-time"}}},"BetaProgramAdoption":{"type":"object","required":["programId","window","participants","activeParticipants","activeActorsWithEvents","events","adoptionRate","samples"],"properties":{"programId":{"type":"string"},"window":{"type":"string","enum":["24h","7d","30d"]},"participants":{"type":"integer"},"activeParticipants":{"type":"integer"},"activeActorsWithEvents":{"type":"integer"},"events":{"type":"integer"},"adoptionRate":{"type":"number"},"samples":{"type":"array","items":{"type":"object","properties":{"actorId":{"type":"string"},"events":{"type":"integer"},"lastSeenAt":{"type":"string","format":"date-time"}}}}}},"DataGovernancePropertyRule":{"type":"object","required":["target","path","action"],"properties":{"target":{"type":"string","enum":["metadata","event.properties","error.context","span.input","span.output","span.error","breadcrumb.data","replay.event.data","identity.traits"]},"path":{"type":"string","examples":["user.email","headers.authorization"]},"action":{"type":"string","enum":["mask","block"]}}},"DataGovernancePolicy":{"type":"object","required":["projectId","environmentId","retentionPolicy","propertyRules"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"retentionPolicy":{"type":"object","description":"Closed per-category project/environment overrides in days. Omitted categories use their corresponding installation defaults; clicks, replays, and webVitals inherit RETENTION_EVENTS_DAYS. Unknown categories are rejected.","properties":{"events":{"type":"integer","minimum":1,"maximum":3650},"errors":{"type":"integer","minimum":1,"maximum":3650},"traces":{"type":"integer","minimum":1,"maximum":3650},"spans":{"type":"integer","minimum":1,"maximum":3650},"llmCalls":{"type":"integer","minimum":1,"maximum":3650},"profiles":{"type":"integer","minimum":1,"maximum":3650},"breadcrumbs":{"type":"integer","minimum":1,"maximum":3650},"webVitals":{"type":"integer","minimum":1,"maximum":3650},"clicks":{"type":"integer","minimum":1,"maximum":3650},"replays":{"type":"integer","minimum":1,"maximum":3650}},"additionalProperties":false,"examples":[{"events":90,"errors":180,"traces":30}]},"propertyRules":{"type":"array","items":{"$ref":"#/components/schemas/DataGovernancePropertyRule"}},"updatedByUserId":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CodeIntegration":{"type":"object","required":["id","projectId","provider","name","owner","repo","webBaseUrl"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"provider":{"type":"string","enum":["github","gitlab"]},"name":{"type":"string","examples":["Web app"]},"owner":{"type":"string","examples":["acme"]},"repo":{"type":"string","examples":["web"]},"webBaseUrl":{"type":"string","format":"uri"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"}}},"LlmPriceOverride":{"type":"object","required":["id","projectId","provider","model","aliases","inputUsdPerMillion","outputUsdPerMillion","cachedInputUsdPerMillion","effectiveFrom"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"provider":{"type":"string","description":"Normalised provider (for example `azure-openai` is stored as `openai`).","examples":["openai"]},"model":{"type":"string","description":"Normalised model id: lower-cased with any `vendor/` prefix removed.","examples":["gpt-4o"]},"aliases":{"type":"array","items":{"type":"string"},"description":"Other model ids that resolve to this price."},"inputUsdPerMillion":{"type":"number","minimum":0,"description":"USD per 1M input tokens."},"outputUsdPerMillion":{"type":"number","minimum":0,"description":"USD per 1M output tokens."},"cachedInputUsdPerMillion":{"type":["number","null"],"minimum":0,"description":"USD per 1M cached input tokens. Stored for completeness; the ingestion contract has no cached-token field yet, so it is not applied."},"effectiveFrom":{"type":"string","format":"date","description":"UTC date from which this price applies."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"IncidentExternalLink":{"type":"object","required":["id","projectId","environmentId","errorGroupId","provider","externalKey","title","url","state"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"errorGroupId":{"type":"string"},"integrationId":{"type":["string","null"]},"provider":{"type":"string","enum":["github","gitlab"]},"externalKey":{"type":"string","examples":["42"]},"title":{"type":"string"},"url":{"type":"string","format":"uri"},"state":{"type":"string","examples":["open"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"IncidentIssueDraft":{"type":"object","required":["provider","integrationId","title","body","url"],"properties":{"provider":{"type":"string","enum":["github","gitlab"]},"integrationId":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"url":{"type":"string","format":"uri"}}},"ErrorGroupRecord":{"type":"object","required":["id","projectId","environmentId","groupingFingerprint","message","type","topStackFrame","severity","status","priority","firstSeenAt","lastSeenAt","lastRegressedAt","occurrenceCount","affectedUsersCount","affectedTenantsCount","latestErrorId","latestRelease","resolvedAt","ignoredAt","assignedToUserId","assignedTo","silencedUntil","incidentNumber","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"groupingFingerprint":{"type":"string"},"message":{"type":"string"},"type":{"type":["string","null"]},"topStackFrame":{"type":["string","null"]},"severity":{"type":"string"},"status":{"type":"string","enum":["open","investigating","resolved","ignored"]},"priority":{"type":["string","null"],"enum":["urgent","high","normal","low",null]},"firstSeenAt":{"type":"string","format":"date-time"},"lastSeenAt":{"type":"string","format":"date-time"},"lastRegressedAt":{"type":["string","null"],"format":"date-time"},"occurrenceCount":{"type":"integer","minimum":0},"affectedUsersCount":{"type":"integer","minimum":0},"affectedTenantsCount":{"type":"integer","minimum":0},"latestErrorId":{"type":["string","null"]},"latestRelease":{"type":["string","null"]},"resolvedAt":{"type":["string","null"],"format":"date-time"},"ignoredAt":{"type":["string","null"],"format":"date-time"},"assignedToUserId":{"type":["string","null"]},"assignedTo":{"type":["object","null"],"properties":{"id":{"type":"string"},"email":{"type":"string"}}},"silencedUntil":{"type":["string","null"],"format":"date-time"},"incidentNumber":{"type":["string","null"]},"trend":{"type":"array","items":{"type":"number"},"description":"Optional recent-occurrence sparkline series."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ErrorGroupTriagePatch":{"type":"object","minProperties":1,"description":"At least one of status, priority, or assignedToUserId must be present.","properties":{"status":{"type":"string","enum":["open","investigating","resolved","ignored"]},"priority":{"type":["string","null"],"enum":["urgent","high","normal","low",null]},"assignedToUserId":{"type":["string","null"],"description":"User id to assign, or null to unassign."}}},"TriageNoteInput":{"type":"object","required":["body"],"properties":{"body":{"type":"string","minLength":1,"maxLength":5000}}},"SilenceIncidentInput":{"type":"object","required":["minutes"],"properties":{"minutes":{"type":["integer","null"],"minimum":0,"description":"Minutes from now to silence the incident. `0` or `null` clears an existing silence."}}},"TriageNoteRecord":{"type":"object","required":["id","errorGroupId","authorUserId","authorEmail","body","createdAt"],"properties":{"id":{"type":"string"},"errorGroupId":{"type":"string"},"authorUserId":{"type":["string","null"]},"authorEmail":{"type":"string"},"body":{"type":"string","maxLength":5000},"createdAt":{"type":"string","format":"date-time"}}},"EntityTenantSummary":{"type":"object","required":["tenantId","label","traits","keyTraits","isUnassigned","impactScore","firstSeenAt","lastSeenAt","profileUpdatedAt","events","errors","openErrors","severeErrors","traces","failedTraces","llmCalls","failedLlmCalls","llmCostUsd","activeUsers","activeSessions"],"properties":{"tenantId":{"type":["string","null"]},"label":{"type":"string"},"traits":{"type":"object","additionalProperties":true},"keyTraits":{"type":"object","additionalProperties":{"type":"string"}},"isUnassigned":{"type":"boolean"},"impactScore":{"type":"number"},"firstSeenAt":{"type":["string","null"],"format":"date-time"},"lastSeenAt":{"type":["string","null"],"format":"date-time"},"profileUpdatedAt":{"type":["string","null"],"format":"date-time"},"events":{"type":"integer","minimum":0},"errors":{"type":"integer","minimum":0},"openErrors":{"type":"integer","minimum":0},"severeErrors":{"type":"integer","minimum":0},"traces":{"type":"integer","minimum":0},"failedTraces":{"type":"integer","minimum":0},"llmCalls":{"type":"integer","minimum":0},"failedLlmCalls":{"type":"integer","minimum":0},"llmCostUsd":{"type":"string"},"activeUsers":{"type":"integer","minimum":0},"activeSessions":{"type":"integer","minimum":0}}},"EngagementMetrics":{"type":"object","description":"Engagement for one period. Engaged-time figures describe only sessions that reported a `$pageleave` (`engagedSessions`); they are null, never 0, when none did.","required":["sessions","pageviews","engagedSessions","totalEngagedMs","medianEngagedMs","meanEngagedMs","medianPagesPerSession","meanPagesPerSession","bounceRate"],"properties":{"sessions":{"type":"integer","minimum":0,"description":"Sessions with at least one pageview."},"pageviews":{"type":"integer","minimum":0},"engagedSessions":{"type":"integer","minimum":0},"totalEngagedMs":{"type":["number","null"]},"medianEngagedMs":{"type":["number","null"]},"meanEngagedMs":{"type":["number","null"]},"medianPagesPerSession":{"type":["number","null"]},"meanPagesPerSession":{"type":["number","null"]},"bounceRate":{"type":["number","null"],"minimum":0,"maximum":1}}},"EntityUserSummary":{"type":"object","required":["userId","label","traits","keyTraits","isAnonymous","impactScore","firstSeenAt","lastSeenAt","profileUpdatedAt","events","errors","openErrors","severeErrors","traces","failedTraces","llmCalls","failedLlmCalls","llmCostUsd","activeTenants","activeSessions"],"properties":{"userId":{"type":["string","null"]},"label":{"type":"string"},"traits":{"type":"object","additionalProperties":true},"keyTraits":{"type":"object","additionalProperties":{"type":"string"}},"isAnonymous":{"type":"boolean"},"impactScore":{"type":"number"},"firstSeenAt":{"type":["string","null"],"format":"date-time"},"lastSeenAt":{"type":["string","null"],"format":"date-time"},"profileUpdatedAt":{"type":["string","null"],"format":"date-time"},"events":{"type":"integer","minimum":0},"errors":{"type":"integer","minimum":0},"openErrors":{"type":"integer","minimum":0},"severeErrors":{"type":"integer","minimum":0},"traces":{"type":"integer","minimum":0},"failedTraces":{"type":"integer","minimum":0},"llmCalls":{"type":"integer","minimum":0},"failedLlmCalls":{"type":"integer","minimum":0},"llmCostUsd":{"type":"string"},"activeTenants":{"type":"integer","minimum":0},"activeSessions":{"type":"integer","minimum":0}}},"ReleaseMetadata":{"type":"object","required":["id","projectId","environmentId","release"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"release":{"type":"string","examples":["web@1.2.3"]},"integrationId":{"type":["string","null"]},"commitSha":{"type":["string","null"]},"commitUrl":{"type":["string","null"],"format":"uri"},"pullRequestNumber":{"type":["integer","null"]},"pullRequestUrl":{"type":["string","null"],"format":"uri"},"deployedBy":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"WarehouseDestination":{"type":"object","required":["id","projectId","environmentId","name","destinationType","connectionUrlPreview","datasets","cursor","batchSize","enabled"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"name":{"type":"string"},"destinationType":{"type":"string","enum":["postgres"]},"connectionUrlPreview":{"type":"string","description":"Redacted connection URL. The raw URL is write-only and never returned."},"datasets":{"type":"array","minItems":1,"maxItems":6,"description":"Selected incremental datasets. Identity profiles preserve traits and use a project/environment/actor source id for idempotent destination upserts.","items":{"type":"string","enum":["events","errors","traces","llmCalls","userProfiles","tenantProfiles"]}},"cursor":{"type":"object","additionalProperties":true},"batchSize":{"type":"integer","minimum":1,"maximum":5000},"enabled":{"type":"boolean"},"lastRunAt":{"type":["string","null"],"format":"date-time"},"lastSuccessAt":{"type":["string","null"],"format":"date-time"},"lastFailureAt":{"type":["string","null"],"format":"date-time"},"lastErrorMessage":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":["string","null"],"format":"date-time"}}},"WarehouseExportRun":{"type":"object","required":["id","destinationId","projectId","environmentId","trigger","status","startedAt","exported"],"properties":{"id":{"type":"string"},"destinationId":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"trigger":{"type":"string","enum":["scheduled","manual","retry"]},"status":{"type":"string","enum":["running","success","failed"]},"startedAt":{"type":"string","format":"date-time"},"finishedAt":{"type":["string","null"],"format":"date-time"},"cursorBefore":{"type":"object","additionalProperties":true},"cursorAfter":{"type":"object","additionalProperties":true},"exported":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"errorMessage":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}},"EventPayload":{"type":"object","required":["name"],"description":"Product or business event. Include stable identity and release fields whenever possible so the console can filter by tenant, user, session, trace, source, and deploy version.","properties":{"name":{"type":"string","description":"Event name using a stable dot-case convention.","examples":["checkout.started"]},"tenant_id":{"type":"string","description":"Stable tenant/workspace/account id."},"user_id":{"type":"string","description":"Stable authenticated user id."},"session_id":{"type":"string","description":"Client or server session id used to connect related activity."},"trace_id":{"type":"string","description":"Trace id when this event belongs to a larger workflow."},"replay_id":{"type":"string","description":"Optional privacy-safe replay id. Send the same id to /v1/replays to show product event markers in the replay timeline."},"source":{"type":"string","description":"Emitter or service name.","examples":["web"]},"release":{"type":"string","description":"Application version or deploy id.","examples":["2026.05.24"]},"properties":{"type":"object","description":"Event-specific attributes. Avoid secrets, tokens, cookies, and full request/response bodies.","additionalProperties":true},"metadata":{"type":"object","description":"Operational metadata such as request id, module, route, or correlation id.","additionalProperties":true},"timestamp":{"type":"string","format":"date-time","description":"Optional event timestamp. Defaults to server receive time when omitted."}}},"ErrorPayload":{"type":"object","required":["message"],"description":"Exception or error occurrence. Use fingerprint to control grouping when the default grouping is too broad or too noisy.","properties":{"message":{"type":"string","description":"Human-readable error message."},"type":{"type":"string","description":"Exception class, error name, or domain error type."},"severity":{"type":"string","enum":["debug","info","warning","error","critical","fatal"],"description":"Severity used by filters and alerting. Defaults to error."},"fingerprint":{"type":"string","description":"Optional grouping key. Events with the same fingerprint are grouped together."},"replay_id":{"type":"string","description":"Optional privacy-safe replay id. Send the same id to /v1/replays so incident detail can show the masked timeline around this error."},"stack":{"type":"string","description":"Raw stack trace. Source maps can resolve minified browser frames when uploaded for the matching release."},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"session_id":{"type":"string"},"trace_id":{"type":"string"},"source":{"type":"string","description":"Emitter or service name, for example web, api, worker, or scheduler."},"release":{"type":"string","description":"Application version or deploy id."},"context":{"type":"object","description":"Debug context for this occurrence. Avoid secrets and full payload bodies.","additionalProperties":true},"metadata":{"type":"object","description":"Operational metadata such as route, module, request id, or correlation id.","additionalProperties":true},"timestamp":{"type":"string","format":"date-time"}}},"BreadcrumbPayload":{"type":"object","required":["type","message"],"properties":{"type":{"type":"string","enum":["navigation","click","console","network","custom"]},"category":{"type":"string"},"message":{"type":"string"},"level":{"type":"string","enum":["debug","info","warning","error","fatal"]},"data":{"type":"object","additionalProperties":true},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"session_id":{"type":"string"},"trace_id":{"type":"string"},"source":{"type":"string"},"release":{"type":"string"},"metadata":{"type":"object","additionalProperties":true},"timestamp":{"type":"string","format":"date-time"}}},"ClickEventPayload":{"type":"object","required":["route","selector","x","y","viewport_width","viewport_height"],"description":"Opt-in browser click map sample. Stores normalized viewport coordinates and privacy-safe selectors only; do not send text content, form values, DOM snapshots, or screenshots.","properties":{"route":{"type":"string","description":"Browser route or path where the click occurred.","examples":["/checkout"]},"selector":{"type":"string","description":"Stable safe selector. Prefer a deliberate data-sigmon-id value instead of generated DOM paths.","examples":["[data-sigmon-id=\"checkout-submit\"]"]},"element_tag":{"type":"string","description":"Optional lower-case element tag, for example button or a."},"element_role":{"type":"string","description":"Optional ARIA role when available."},"x":{"type":"number","minimum":0,"maximum":1,"description":"Normalized viewport x coordinate from 0 to 1."},"y":{"type":"number","minimum":0,"maximum":1,"description":"Normalized viewport y coordinate from 0 to 1."},"viewport_width":{"type":"integer","minimum":1},"viewport_height":{"type":"integer","minimum":1},"scroll_x":{"type":"integer"},"scroll_y":{"type":"integer"},"masked":{"type":"boolean","default":true,"description":"True when the SDK captured the click through the privacy-safe browser helper."},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"session_id":{"type":"string"},"trace_id":{"type":"string"},"source":{"type":"string","examples":["web"]},"release":{"type":"string","description":"Application version or deploy id."},"metadata":{"type":"object","additionalProperties":true},"timestamp":{"type":"string","format":"date-time"}}},"VisualReplayChunk":{"type":"object","required":["v","replay_id","seq","events"],"properties":{"v":{"type":"integer","const":1},"replay_id":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$","description":"Same id as the /v1/replays timeline and the error/event replay_id."},"seq":{"type":"integer","minimum":0,"maximum":399,"description":"Zero-based chunk order within the replay; the first chunk carries the full DOM snapshot."},"mask_all_text":{"type":"boolean","default":true,"description":"The SDK masked every text node in the browser. The server also masks all text when this is not explicitly false."},"events":{"type":"array","maxItems":20000,"items":{"type":"object","required":["type","timestamp","data"],"properties":{"type":{"type":"integer","minimum":0,"maximum":6},"timestamp":{"type":"integer"},"data":{}}}}}},"SessionReplayPayload":{"type":"object","required":["replay_id","started_at"],"description":"Privacy-safe browser session timeline linked to errors through replay_id. This is not video replay and must not include screenshots, DOM snapshots, raw text, input values, passwords, cookies, or HTML. The complete JSON payload must not exceed 64 KiB.","properties":{"replay_id":{"type":"string","description":"Stable id generated by the browser SDK for this replay buffer."},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":"string","format":"date-time"},"duration_ms":{"type":"integer","minimum":0},"route":{"type":"string","description":"Browser route or path where the replay started."},"error_id":{"type":"string","description":"Optional error id when available after capture."},"masked":{"type":"boolean","default":true},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"session_id":{"type":"string"},"trace_id":{"type":"string"},"source":{"type":"string","examples":["web"]},"release":{"type":"string"},"metadata":{"type":"object","additionalProperties":true},"events":{"type":"array","maxItems":300,"description":"Ordered privacy-safe timeline, limited to 300 events per replay payload.","items":{"type":"object","additionalProperties":false,"required":["offset_ms","type"],"properties":{"offset_ms":{"type":"integer","minimum":0},"type":{"type":"string","enum":["navigation","click","input","console","network","error","custom"]},"route":{"type":"string"},"selector":{"type":"string","description":"Stable safe selector, preferably based on data-sigmon-id."},"message":{"type":"string","description":"Optional source message. The API always stores it as the literal [REDACTED]."},"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1},"data":{"type":"object","additionalProperties":true,"description":"Privacy-safe JSON metadata limited to 5 container levels and 64 object keys in total for this event. Keys that can carry raw text, HTML, input values, or passwords are rejected."}}}},"timestamp":{"type":"string","format":"date-time"}}},"LlmPayload":{"type":"object","required":["provider","model"],"properties":{"provider":{"type":"string","examples":["openai"]},"model":{"type":"string","examples":["gpt-5-mini"]},"prompt_name":{"type":"string"},"status":{"type":"string","enum":["success","error","pending"]},"input_tokens":{"type":"integer","minimum":0},"output_tokens":{"type":"integer","minimum":0},"cost_usd":{"type":"number","minimum":0,"description":"Cost reported by the caller; an explicit 0 is kept as a free call. Omit it to let the worker estimate the cost from the project's price overrides and then the built-in pricing catalog (provider + model + token counts); unknown models are stored with cost_source = unknown."},"latency_ms":{"type":"integer","minimum":0},"cached_input_tokens":{"type":"integer","minimum":0,"description":"The subset of input_tokens served from the provider's prompt cache. Priced at the cached rate when the worker estimates the cost."},"input_preview":{"type":"string"},"output_preview":{"type":"string"},"input_content":{"type":"string","maxLength":100000,"description":"Full prompt, shown in the console call detail to members and admins. Send it only when your own policy allows storing it; credential patterns are redacted, other personal data is not. Dropped when LLM_CONTENT_CAPTURE_ENABLED=false and removed after RETENTION_LLM_CONTENT_DAYS."},"output_content":{"type":"string","maxLength":100000,"description":"Full response. Same rules as input_content."},"input_content_truncated":{"type":"boolean","description":"Set by the client when input_content was cut to fit."},"output_content_truncated":{"type":"boolean","description":"Set by the client when output_content was cut to fit."},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"trace_id":{"type":"string"},"metadata":{"type":"object","additionalProperties":true},"timestamp":{"type":"string","format":"date-time"}}},"WebVitalPayload":{"type":"object","required":["name","value"],"description":"Browser Web Vital sample. Use the browser SDK helper when possible so metric names, ratings, route, navigation type, release, and context are normalized consistently.","properties":{"name":{"type":"string","enum":["CLS","FCP","FID","INP","LCP","TTFB"]},"value":{"type":"number","minimum":0,"description":"Metric value. CLS is unitless; timing metrics are milliseconds."},"rating":{"type":"string","enum":["good","needs-improvement","poor"],"default":"good"},"route":{"type":"string","description":"Browser route or path where the metric was observed."},"navigation_type":{"type":"string","description":"Browser navigation type such as navigate, reload, back-forward, or prerender."},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"session_id":{"type":"string"},"trace_id":{"type":"string"},"source":{"type":"string","examples":["web"]},"release":{"type":"string","description":"Application version or deploy id used for regression comparison."},"metadata":{"type":"object","additionalProperties":true},"timestamp":{"type":"string","format":"date-time"}}},"ProfilePayload":{"type":"object","required":["name","kind","started_at"],"description":"Bounded runtime profile summary. Use @sigmon/sdk/node helpers for targeted CPU windows and memory snapshots; do not upload raw heap dumps or full profiler files.","properties":{"name":{"type":"string","description":"Route, job, worker task, or operation being profiled."},"kind":{"type":"string","enum":["cpu","memory"]},"runtime":{"type":"string","default":"node"},"service":{"type":"string","description":"Service or process name, for example api, worker, scheduler."},"route":{"type":"string","description":"HTTP route or job name when applicable."},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":"string","format":"date-time"},"duration_ms":{"type":"integer","minimum":0},"sample_count":{"type":"integer","minimum":0},"sampling_interval_ms":{"type":"integer","minimum":1},"cpu_usage_percent":{"type":"number","minimum":0,"maximum":100},"cpu_user_ms":{"type":"integer","minimum":0},"cpu_system_ms":{"type":"integer","minimum":0},"rss_bytes":{"type":"integer","minimum":0},"heap_used_bytes":{"type":"integer","minimum":0},"heap_total_bytes":{"type":"integer","minimum":0},"external_bytes":{"type":"integer","minimum":0},"array_buffers_bytes":{"type":"integer","minimum":0},"top_functions":{"type":"array","maxItems":100,"items":{"type":"object","required":["function_name"],"properties":{"function_name":{"type":"string"},"url":{"type":"string"},"line_number":{"type":"integer","minimum":0},"column_number":{"type":"integer","minimum":0},"self_time_ms":{"type":"number","minimum":0},"total_time_ms":{"type":"number","minimum":0},"sample_count":{"type":"integer","minimum":0}}}},"summary":{"type":"object","additionalProperties":true},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"session_id":{"type":"string"},"trace_id":{"type":"string"},"source":{"type":"string","examples":["node"]},"release":{"type":"string"},"metadata":{"type":"object","additionalProperties":true},"timestamp":{"type":"string","format":"date-time"}}},"TracePayload":{"type":"object","required":["name","started_at"],"properties":{"name":{"type":"string"},"status":{"type":"string","enum":["success","error","pending"]},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":"string","format":"date-time"},"duration_ms":{"type":"integer","minimum":0},"trace_id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"session_id":{"type":"string"},"source":{"type":"string"},"release":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}},"SpanPayload":{"type":"object","required":["trace_id","name","started_at"],"properties":{"trace_id":{"type":"string"},"parent_span_id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["success","error","pending"]},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":"string","format":"date-time"},"duration_ms":{"type":"integer","minimum":0},"input":{"description":"Any JSON value. Avoid secrets and full payload bodies."},"output":{"description":"Any JSON value. Avoid secrets and full payload bodies."},"error":{"description":"Any JSON value describing a failed child operation."},"cost_usd":{"type":"number","minimum":0},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"session_id":{"type":"string"},"source":{"type":"string"},"release":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}},"UserIdentifyPayload":{"type":"object","required":["user_id","traits"],"description":"Upserts a project/environment-scoped user profile. Identify traits shallow-merge into existing stored traits. Telemetry with matching user_id updates last_seen_at, but only identify calls update stored traits.","properties":{"user_id":{"type":"string","description":"Stable authenticated user id from the monitored product."},"tenant_id":{"type":"string","description":"Optional current tenant/workspace/account id for this user."},"traits":{"type":"object","description":"Sanitized profile traits such as name, email, role, plan, locale, or operation mode. Secrets are not allowed.","additionalProperties":true,"examples":[{"name":"Ana Souza","email":"ana@example.com","role":"admin","plan":"pro"}]},"metadata":{"type":"object","description":"Accepted for envelope compatibility but not persisted in profile rows in this MVP.","additionalProperties":true},"timestamp":{"type":"string","format":"date-time","description":"Optional identify timestamp."}}},"TenantIdentifyPayload":{"type":"object","required":["tenant_id","traits"],"description":"Upserts a project/environment-scoped tenant profile used by Entities investigation views and tenant-level filters. Identify traits shallow-merge into existing stored traits.","properties":{"tenant_id":{"type":"string","description":"Stable tenant/workspace/account id from the monitored product."},"traits":{"type":"object","description":"Sanitized tenant traits such as name, plan, status, tier, region, or operation_mode. Secrets are not allowed.","additionalProperties":true,"examples":[{"name":"MicroERP","plan":"pro","operation_mode":"production"}]},"metadata":{"type":"object","description":"Accepted for envelope compatibility but not persisted in profile rows in this MVP.","additionalProperties":true},"timestamp":{"type":"string","format":"date-time","description":"Optional identify timestamp."}}},"LoginPayload":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","format":"password"}}},"HttpMonitorPayload":{"type":"object","required":["projectId","environmentId","name","url"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"notificationChannelId":{"type":["string","null"]},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"method":{"type":"string","enum":["GET","HEAD"],"default":"GET"},"intervalMinutes":{"type":"integer","minimum":1,"default":5},"timeoutMs":{"type":"integer","minimum":100,"maximum":60000,"default":5000},"expectedStatus":{"type":"string","examples":["2xx","200","200-299"]},"bodyContains":{"type":["string","null"]},"failureThreshold":{"type":"integer","minimum":1,"default":2},"recoveryThreshold":{"type":"integer","minimum":1,"default":2},"enabled":{"type":"boolean","default":true}}},"HeartbeatMonitorPayload":{"type":"object","required":["projectId","environmentId","name","expectedIntervalMinutes"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"notificationChannelId":{"type":["string","null"]},"name":{"type":"string"},"expectedIntervalMinutes":{"type":"integer","minimum":1},"graceMinutes":{"type":"integer","minimum":0,"default":0},"enabled":{"type":"boolean","default":true}}},"CreateReadTokenPayload":{"type":"object","required":["projectId","environmentId","name"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":256}}},"UpdateReadTokenPayload":{"type":"object","minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":256}}},"ReadToken":{"type":"object","required":["id","projectId","environmentId","name","prefix","createdAt","lastUsedAt","revokedAt"],"properties":{"id":{"type":"string","examples":["rdtok_example"]},"projectId":{"type":"string"},"environmentId":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string","description":"First 16 characters of the secret, safe to display for identification."},"createdAt":{"type":"string","format":"date-time"},"lastUsedAt":{"type":["string","null"],"format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"}}},"ReadTokenCreateResponse":{"type":"object","required":["token"],"properties":{"token":{"allOf":[{"$ref":"#/components/schemas/ReadToken"},{"type":"object","required":["secret"],"properties":{"secret":{"type":"string","description":"Full read token secret, for example `shread_...`. Returned only on creation — store it now, it cannot be retrieved again."}}}]}}},"ReadTokenResponse":{"type":"object","required":["token"],"properties":{"token":{"$ref":"#/components/schemas/ReadToken"}}},"ReadTokenListResponse":{"type":"object","required":["tokens"],"properties":{"tokens":{"type":"array","items":{"$ref":"#/components/schemas/ReadToken"}}}},"MonitorResponse":{"type":"object","required":["monitor"],"properties":{"monitor":{"type":"object","additionalProperties":true,"description":"Monitor record with secretHash redacted."},"secret":{"type":"string","description":"Heartbeat secret returned only when creating a heartbeat monitor."}}},"DeadLetterJob":{"type":"object","required":["id","projectId","environmentId","queueName","jobName","payload","errorMessage","createdAt"],"properties":{"id":{"type":"string"},"projectId":{"type":["string","null"],"description":"Project scope captured from the failed telemetry job when available."},"environmentId":{"type":["string","null"],"description":"Environment scope captured from the failed telemetry job when available."},"queueName":{"type":"string","examples":["telemetry"]},"jobName":{"type":"string","examples":["event"]},"payload":{"type":"object","description":"sanitized failed job payload retained for operator inspection.","additionalProperties":true},"errorMessage":{"type":"string","description":"Sanitized failure message."},"createdAt":{"type":"string","format":"date-time"}}},"DeadLetterJobListResponse":{"type":"object","required":["deadLetterJobs"],"properties":{"deadLetterJobs":{"type":"array","items":{"$ref":"#/components/schemas/DeadLetterJob"}},"cursor":{"type":"string","nullable":true,"description":"Opaque cursor for the next newest-first page."}}},"DeadLetterJobResponse":{"type":"object","required":["deadLetterJob"],"properties":{"deadLetterJob":{"$ref":"#/components/schemas/DeadLetterJob"}}},"DeadLetterJobAction":{"type":"object","required":["id","deadLetterJobId","queueName","jobName","action","actorEmail","metadata","createdAt"],"properties":{"id":{"type":"string"},"deadLetterJobId":{"type":"string"},"queueName":{"type":"string"},"jobName":{"type":"string"},"action":{"type":"string","enum":["deleted","replayed","expired"]},"actorUserId":{"type":"string","nullable":true},"actorEmail":{"type":"string"},"metadata":{"type":"object","additionalProperties":true},"createdAt":{"type":"string","format":"date-time"}}},"DeadLetterJobActionsResponse":{"type":"object","required":["actions"],"properties":{"actions":{"type":"array","items":{"$ref":"#/components/schemas/DeadLetterJobAction"}}}},"DeadLetterReplayResponse":{"type":"object","required":["replayed","id"],"properties":{"replayed":{"type":"boolean","const":true},"id":{"type":"string"}}},"SystemActionResponse":{"type":"object","required":["ok","action","status","message","generatedAt"],"properties":{"ok":{"type":"boolean","const":true},"action":{"type":"string","enum":["doctor","retention"]},"status":{"type":"string","enum":["success","skipped"]},"message":{"type":"string"},"ran":{"type":"boolean"},"skipped":{"type":"boolean"},"generatedAt":{"type":"string","format":"date-time"}}},"SystemBackupActionResponse":{"type":"object","required":["ok","action","status","message","jobId","generatedAt"],"properties":{"ok":{"type":"boolean","const":true},"action":{"type":"string","const":"backup"},"status":{"type":"string","const":"accepted"},"message":{"type":"string","const":"Backup queued."},"jobId":{"type":"string"},"generatedAt":{"type":"string","format":"date-time"}}},"SystemHealthSample":{"type":"object","required":["capturedAt","postgresLatencyMs","redisLatencyMs","queueWaiting","queueActive","queueFailed"],"properties":{"capturedAt":{"type":"string","format":"date-time"},"postgresLatencyMs":{"type":["number","null"]},"redisLatencyMs":{"type":["number","null"]},"queueWaiting":{"type":"integer","minimum":0},"queueActive":{"type":"integer","minimum":0},"queueFailed":{"type":"integer","minimum":0}}},"AlertEventRecord":{"type":"object","required":["id","projectId","environmentId","status","severity","triggeredAt","windowStart","windowEnd","observedValue","threshold","message","metadata","createdAt"],"properties":{"id":{"type":"string"},"ruleId":{"type":["string","null"]},"monitorId":{"type":["string","null"]},"projectId":{"type":"string"},"environmentId":{"type":"string"},"status":{"type":"string","enum":["triggered","acknowledged","snoozed","resolved"]},"severity":{"type":"string","enum":["info","warning","critical"]},"triggeredAt":{"type":"string","format":"date-time"},"windowStart":{"type":"string","format":"date-time"},"windowEnd":{"type":"string","format":"date-time"},"observedValue":{"type":"string"},"threshold":{"type":"string"},"message":{"type":"string"},"metadata":{"type":["object","null"],"additionalProperties":true},"acknowledgedAt":{"type":["string","null"],"format":"date-time"},"acknowledgedByUserId":{"type":["string","null"]},"acknowledgedByEmail":{"type":["string","null"]},"resolvedAt":{"type":["string","null"],"format":"date-time"},"resolvedByUserId":{"type":["string","null"]},"resolvedByEmail":{"type":["string","null"]},"snoozedUntil":{"type":["string","null"],"format":"date-time"},"triageNote":{"type":["string","null"]},"escalationDueAt":{"type":["string","null"],"format":"date-time"},"escalatedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"latestDeliveryStatus":{"type":["string","null"],"enum":["success","failed",null]}}},"AlertEventTriagePatch":{"type":"object","required":["status"],"description":"`snoozedUntil` is required and must be a valid date when `status` is `snoozed`.","properties":{"status":{"type":"string","enum":["triggered","acknowledged","snoozed","resolved"]},"snoozedUntil":{"type":["string","null"],"format":"date-time"},"note":{"type":["string","null"],"maxLength":2000}}},"AlertSuggestion":{"type":"object","description":"Heuristic alert rule suggestion derived from recent error, latency, LLM cost, or dead-letter activity. Suggestions are omitted when an active rule of the same type (and route pattern, where applicable) already exists.","required":["key","type","severity","title","sub","windowMinutes","threshold","rationale","cooldownMinutes"],"properties":{"key":{"type":"string"},"type":{"type":"string","enum":["critical_errors","error_count","error_rate","trace_p95_latency","llm_cost","dead_letter_count"]},"severity":{"type":"string","enum":["info","warning","critical"]},"title":{"type":"string"},"sub":{"type":"string"},"windowMinutes":{"type":"integer","minimum":1},"threshold":{"type":"string"},"routePattern":{"type":["string","null"]},"minimumSampleSize":{"type":"integer","minimum":0},"rationale":{"type":"string"},"cooldownMinutes":{"type":"integer","minimum":0}}}},"responses":{"BadRequest":{"description":"Invalid request payload or query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Missing or invalid authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Forbidden":{"description":"Authenticated caller is not allowed to perform this action. Console users have one role: `admin` (everything), `member` (read everything and triage telemetry), or `viewer` (read-only). A role below the operation's `x-required-role` answers `{ error: \"admin_required\" }` or `{ error: \"role_required\", requiredRole }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"FeatureNotInPlan":{"description":"The feature behind this route is not included in the installation's edition (`SIGMON_EDITION`). Body: `{ error: \"feature_not_in_plan\", feature }`. Ingestion is never gated.","content":{"application/json":{"schema":{"type":"object","required":["error","feature"],"properties":{"error":{"type":"string","enum":["feature_not_in_plan"]},"feature":{"type":"string"}}}}}},"InstanceReadOnly":{"description":"The instance is read-only because of a billing problem (`SIGMON_READ_ONLY=true`, set by Sigmon Cloud during the payment grace period). Every POST/PUT/PATCH/DELETE outside `/v1/*`, `POST /auth/login` and `POST /auth/logout` answers this before authentication. Reads and ingestion keep working. Body: `{ error: \"instance_read_only\" }`.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["instance_read_only"]}}}}}},"Unavailable":{"description":"Service dependency unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"TooManyRequests":{"description":"Ingestion is quota'd per API key (or per source IP when unauthenticated), shared across all /v1 ingestion and identify endpoints. Retry after the seconds given in the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/health":{"get":{"tags":["Health"],"summary":"Check API liveness","description":"Returns the commit currently running as `version`, or `null` when the deployment did not stamp one. Compare it against the commit you expect to confirm a deploy actually replaced the running container.","responses":{"200":{"description":"API is alive","content":{"application/json":{"example":{"ok":true,"version":"e8460fbfef11972f7605a2221fee2d19c452ca9d"}}}}}}},"/ready":{"get":{"tags":["Health"],"summary":"Check API dependencies","responses":{"200":{"description":"Postgres and Redis are ready","content":{"application/json":{"example":{"ok":true,"checks":{"postgres":true,"redis":true}}}}},"503":{"description":"One or more dependencies are not ready","content":{"application/json":{"example":{"ok":false,"checks":{"postgres":true,"redis":false}}}}}}}},"/v1/events":{"post":{"tags":["Ingestion"],"summary":"Ingest an event","description":"Track product or business events. Use this for product analytics, lifecycle events, and domain milestones.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventPayload"},"examples":{"default":{"value":{"name":"checkout.started","tenant_id":"tenant_123","user_id":"user_456","session_id":"sess_789","replay_id":"rpl_browser_123","source":"web","release":"2026.05.24","properties":{"plan":"team","checkout_id":"chk_123"},"metadata":{"request_id":"req_abc"}}}}}}},"responses":{"202":{"description":"Signal accepted for asynchronous persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true,"id":"evt_example"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/surveys/responses":{"post":{"tags":["Ingestion"],"summary":"Ingest an in-app survey response","description":"Track lightweight survey answers collected by browser widgets, SDK calls, or server-side product flows. Responses are scoped to a configured survey and can be linked to user, tenant, session, trace, source, and release context.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyResponsePayload"},"examples":{"default":{"value":{"survey_id":"srv_activation_pulse","actor_type":"user","actor_id":"user_456","tenant_id":"tenant_123","user_id":"user_456","session_id":"sess_789","source":"web","release":"2026.06.01","answers":{"satisfaction":5,"comment":"Great"},"metadata":{"placement":"checkout_success"}}}}}}},"responses":{"202":{"description":"Signal accepted for asynchronous persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true,"id":"evt_example"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/campaigns/events":{"post":{"tags":["Ingestion"],"summary":"Report a campaign lifecycle event","description":"Report that a delivered campaign was shown (`delivered`), `opened`, `clicked`, `dismissed` or led to a `converted` outcome. `queued`, `sent`, `failed` and `opted_out` are recorded by Sigmon itself and are rejected here. Events for a campaign outside the key's project/environment are dropped. Never entitlement-gated.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEventPayload"},"examples":{"default":{"value":{"campaign_id":"cmp_123","type":"clicked","user_id":"user_456","source":"web"}}}}}},"responses":{"202":{"description":"Signal accepted for asynchronous persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true,"id":"evt_example"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/campaigns/active":{"post":{"tags":["Ingestion"],"summary":"Fetch the in-app campaigns for a user","description":"Called by the SDK. Returns the in-app campaigns Sigmon has delivered to the identified `user_id` that are still showable: the campaign is active, the user has not opted out, dismissed or clicked it, and it was shown fewer than its `perUserCap` times. Template variables are already substituted (plain text, not HTML-escaped; the host app renders). Returns an empty list for an anonymous id and on installations where nothing can be scheduled. Never entitlement-gated. Uses POST so user ids stay out of URLs.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"user_id":{"type":"string"},"anonymous_id":{"type":"string"}}},"examples":{"default":{"value":{"user_id":"user_456"}}}}}},"responses":{"200":{"description":"Showable in-app campaigns","content":{"application/json":{"schema":{"type":"object","required":["campaigns"],"properties":{"campaigns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"channel":{"type":"string","enum":["in_app"]},"subject":{"type":["string","null"]},"body":{"type":"string"},"cta_url":{"type":["string","null"],"format":"uri"},"sent_at":{"type":["string","null"],"format":"date-time"}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/campaigns/opt-out":{"post":{"tags":["Ingestion"],"summary":"Record a campaign opt-out","description":"Records that `user_id` opted out of a consent `category` (default `product`), or of one campaign when `campaign_id` is given. Both channels respect it before every send, and in-app fetch hides the campaign. Consent collection stays the host application's responsibility; call this whenever your product records a withdrawal. Never entitlement-gated.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["user_id"],"properties":{"user_id":{"type":"string"},"campaign_id":{"type":"string"},"category":{"type":"string"},"reason":{"type":"string"}}},"examples":{"default":{"value":{"user_id":"user_456","category":"marketing"}}}}}},"responses":{"202":{"description":"Opt-out recorded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentifyAcceptedResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Campaign not found in the key's project/environment"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/campaigns/unsubscribe":{"get":{"tags":["Health"],"summary":"Unsubscribe confirmation page","description":"Landing page of the signed unsubscribe link in every delivered campaign e-mail. Verifies the HMAC token and renders a confirmation form; it never changes state, so mail scanners that pre-fetch links cannot unsubscribe anyone.","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"HTML confirmation page","content":{"text/html":{"schema":{"type":"string"}}}},"400":{"description":"Invalid or altered token","content":{"text/html":{"schema":{"type":"string"}}}}}},"post":{"tags":["Health"],"summary":"Unsubscribe from campaign messages","description":"Records a per-user opt-out for the consent category carried by the signed token. Also serves as the RFC 8058 one-click target named in the `List-Unsubscribe-Post` header (body `List-Unsubscribe=One-Click`).","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Unsubscribed","content":{"text/html":{"schema":{"type":"string"}}}},"400":{"description":"Invalid or altered token","content":{"text/html":{"schema":{"type":"string"}}}},"503":{"description":"Temporarily unavailable","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/terms":{"get":{"tags":["Health"],"summary":"Terms of Service page","description":"Public Sigmon Cloud Terms of Service. Served only on the public landing hosts (`LANDING_HOSTS`); any other host receives 404. Static content, no input.","responses":{"200":{"description":"Rendered HTML page","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"Not served on this host"}}}},"/privacy":{"get":{"tags":["Health"],"summary":"Privacy Policy page","description":"Public Privacy Policy, including sub-processors, retention and deletion. Served only on the public landing hosts (`LANDING_HOSTS`); any other host receives 404. Static content, no input.","responses":{"200":{"description":"Rendered HTML page","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"Not served on this host"}}}},"/dpa":{"get":{"tags":["Health"],"summary":"Data Processing Addendum page","description":"Public summary of the data processing addendum. Served only on the public landing hosts (`LANDING_HOSTS`); any other host receives 404. Static content, no input.","responses":{"200":{"description":"Rendered HTML page","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"Not served on this host"}}}},"/refund":{"get":{"tags":["Health"],"summary":"Refund Policy page","description":"Public 14-day money-back guarantee policy. Served only on the public landing hosts (`LANDING_HOSTS`); any other host receives 404. Static content, no input.","responses":{"200":{"description":"Rendered HTML page","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"Not served on this host"}}}},"/self-hosting":{"get":{"tags":["Health"],"summary":"Self-hosting guide page","description":"Public self-hosting guide rendered from `docs/SELF-HOSTING.md`. Served only on the public landing hosts (`LANDING_HOSTS`); any other host receives 404. Static content, no input.","responses":{"200":{"description":"Rendered HTML page","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"Not served on this host"}}}},"/license":{"get":{"tags":["Health"],"summary":"License page","description":"Public license text rendered from the repository `LICENSE` file. Served only on the public landing hosts (`LANDING_HOSTS`); any other host receives 404. Static content, no input.","responses":{"200":{"description":"Rendered HTML page","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"Not served on this host"}}}},"/landing-telemetry.js":{"get":{"tags":["Health"],"summary":"Landing page telemetry script","description":"Dependency-free script the public landing page loads to send its own launch-funnel events to Sigmon. Served only on the landing hosts (`LANDING_HOSTS`) and only when `LANDING_TELEMETRY_KEY` and `LANDING_TELEMETRY_ENDPOINT` are set; otherwise 404. Static content, no input.","responses":{"200":{"description":"JavaScript source","content":{"application/javascript":{"schema":{"type":"string"}}}},"404":{"description":"Not served on this host or telemetry is not configured"}}}},"/robots.txt":{"get":{"tags":["Health"],"summary":"robots.txt for the landing site","description":"Crawler rules and sitemap pointer for the public landing site. Served only on the landing hosts (`LANDING_HOSTS`); any other host receives 404.","responses":{"200":{"description":"robots.txt","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Not served on this host"}}}},"/sitemap.xml":{"get":{"tags":["Health"],"summary":"sitemap.xml for the landing site","description":"XML sitemap of the public landing pages. Served only on the landing hosts (`LANDING_HOSTS`); any other host receives 404.","responses":{"200":{"description":"XML sitemap","content":{"application/xml":{"schema":{"type":"string"}}}},"404":{"description":"Not served on this host"}}}},"/v1/feedback":{"post":{"tags":["Ingestion"],"summary":"Ingest product feedback","description":"Track text feedback collected by the Sigmon browser feedback widget or a custom product flow. Feedback is scoped to the ingestion key and can include page, actor, release, and metadata context. Optional `replay_id` links the report to an existing session replay and optional `snapshot` attaches a masked DOM snapshot (see the schema); when a `snapshot` was sent the response carries `snapshot_stored`. This is the only ingestion route that accepts bodies up to 2 MiB (413 above that); every other ingestion route keeps the 1 MiB default.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackPayload"},"examples":{"default":{"value":{"message":"The export button is confusing.","category":"ux","tenant_id":"tenant_123","user_id":"user_456","session_id":"sess_789","source":"browser","release":"2026.06.01","page_url":"https://app.example.com/reports","path":"/reports?tab=exports","replay_id":"rpl_abc123","metadata":{"surface":"reports"}}}}}}},"responses":{"202":{"description":"Feedback accepted for asynchronous persistence","content":{"application/json":{"schema":{"type":"object","required":["accepted","id"],"properties":{"accepted":{"type":"boolean","const":true},"id":{"type":"string","description":"Generated feedback id."},"snapshot_stored":{"type":"boolean","description":"Present only when the request carried a `snapshot`. `false` means the snapshot was dropped (storage unavailable, the environment's widget `allowScreenshot` is off, per-key snapshot rate limit, or project disk quota) while the text report was still accepted."}}},"examples":{"accepted":{"value":{"accepted":true,"id":"fbk_example","snapshot_stored":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"413":{"description":"Request body exceeds the 2 MiB limit of this route"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/errors":{"post":{"tags":["Ingestion"],"summary":"Ingest an error","description":"Track exceptions, crashes, and grouped error occurrences. Include stack, release, source, and identity fields to unlock issue detail, source-map resolution, and tenant/user drilldowns.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorPayload"},"examples":{"default":{"value":{"message":"Payment provider timeout","type":"PaymentTimeoutError","severity":"error","fingerprint":"payment-timeout","stack":"PaymentTimeoutError: provider timeout\n    at chargeCustomer","tenant_id":"tenant_123","user_id":"user_456","source":"api","release":"2026.05.24","context":{"provider":"example-pay","operation":"charge"},"metadata":{"request_id":"req_abc"}}}}}}},"responses":{"202":{"description":"Signal accepted for asynchronous persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true,"id":"evt_example"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/breadcrumbs":{"post":{"tags":["Ingestion"],"summary":"Ingest a breadcrumb","description":"Track lightweight session context for navigation, UI, console, network, or custom steps.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreadcrumbPayload"},"examples":{"default":{"value":{"type":"custom","category":"checkout","message":"Selected shipping method"}}}}}},"responses":{"202":{"description":"Signal accepted for asynchronous persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true,"id":"evt_example"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/clicks":{"post":{"tags":["Ingestion"],"summary":"Ingest a browser click map sample","description":"Track opt-in click density by route using normalized coordinates and privacy-safe selectors. Prefer the browser SDK helper so text, values, DOM, and screenshots are never collected.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClickEventPayload"},"examples":{"default":{"value":{"route":"/checkout","selector":"[data-sigmon-id=\"checkout-submit\"]","element_tag":"button","element_role":"button","x":0.72,"y":0.61,"viewport_width":1440,"viewport_height":900,"scroll_x":0,"scroll_y":320,"masked":true,"source":"web","release":"2026.05.24"}}}}}},"responses":{"202":{"description":"Signal accepted for asynchronous persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true,"id":"evt_example"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/replays":{"post":{"tags":["Ingestion"],"summary":"Ingest a privacy-safe session replay","description":"Track a masked browser interaction timeline and link it to errors through replay_id. The payload stores events such as navigation and safe selectors, not screenshots, DOM snapshots, raw text, input values, or HTML.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayPayload"},"examples":{"default":{"value":{"replay_id":"rpl_browser_123","started_at":"2026-06-01T12:00:00.000Z","ended_at":"2026-06-01T12:00:02.000Z","duration_ms":2000,"route":"/checkout","masked":true,"session_id":"sess_789","source":"web","release":"2026.05.24","events":[{"offset_ms":0,"type":"navigation","route":"/checkout","data":{}},{"offset_ms":750,"type":"click","selector":"[data-sigmon-id=\"pay\"]","x":0.52,"y":0.61,"data":{}}]}}}}}},"responses":{"202":{"description":"Signal accepted for asynchronous persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true,"id":"evt_example"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/replays/chunks":{"post":{"tags":["Ingestion"],"summary":"Ingest a visual replay chunk","description":"Upload one chunk of an opt-in visual session replay: a batch of rrweb DOM events (a full snapshot in the first chunk, incremental mutations afterwards), recorded by `@sigmon/sdk/browser/visual-replay` after in-browser masking (inputs and, by default, all text are masked; `data-sigmon-ignore` subtrees are blocked; no canvas, media or pixels). Chunks of one replay are keyed by `replay_id` and ordered by `seq`; the same `replay_id` as the `/v1/replays` timeline links them. The body is gzip-compressed JSON sent with `content-type: application/vnd.sigmon.replay-chunk+gzip` (plain JSON with `application/json` is also accepted). Limits: 1 MiB compressed body (413 above, own limit for this route only), 5 MiB inflated, 20,000 events and 150,000 DOM nodes per chunk, 400 chunks and 25 MiB per replay, plus the per-project `VISUAL_REPLAY_PROJECT_QUOTA_MB` budget. The API re-sanitises every chunk from an allowlist (no scripts, handlers, frames, input values, canvas/media/console payloads, external CSS or image URLs) before writing it to local disk. Replaying the same `seq` is idempotent (`duplicate: true`). When visual replay is disabled, its directory is unusable, or a quota is hit, the chunk is accepted with `stored: false` and a `reason` so the SDK stops sending. Ingestion is never gated by the edition; only reading chunks (`GET /query/replays/{replayId}/visual`) requires Sigmon Pro.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/vnd.sigmon.replay-chunk+gzip":{"schema":{"type":"string","format":"binary","description":"gzip of the JSON document described by `VisualReplayChunk`."}},"application/json":{"schema":{"$ref":"#/components/schemas/VisualReplayChunk"}}}},"responses":{"202":{"description":"Chunk accepted","content":{"application/json":{"schema":{"type":"object","required":["accepted","stored"],"properties":{"accepted":{"type":"boolean","const":true},"stored":{"type":"boolean","description":"False when the chunk was dropped; see `reason`."},"reason":{"type":"string","enum":["disabled","storage_unavailable","replay_limit","quota"]},"seq":{"type":"integer"},"duplicate":{"type":"boolean","description":"True when this replay already had a chunk with the same `seq`."},"dropped_events":{"type":"integer","description":"Events removed by the sanitiser (custom, plugin, canvas, media, malformed)."}}},"examples":{"stored":{"value":{"accepted":true,"stored":true,"seq":0,"dropped_events":0}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"413":{"description":"Compressed body, inflated body, event count or node count above the chunk limits"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/llm":{"post":{"tags":["Ingestion"],"summary":"Ingest an LLM call","description":"Track AI provider calls, latency, status, tokens, and cost.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LlmPayload"},"examples":{"default":{"value":{"provider":"openai","model":"gpt-5-mini","prompt_name":"dashboard_summary","status":"success"}}}}}},"responses":{"202":{"description":"Signal accepted for asynchronous persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true,"id":"evt_example"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/web-vitals":{"post":{"tags":["Ingestion"],"summary":"Ingest Web Vitals","description":"Track browser UX metrics such as LCP, INP, CLS, FCP, FID, and TTFB by route and release.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebVitalPayload"},"examples":{"default":{"value":{"name":"LCP","value":2420,"rating":"needs-improvement","route":"/dashboard","navigation_type":"navigate","source":"web","release":"2026.05.24","metadata":{"effective_type":"4g"}}}}}}},"responses":{"202":{"description":"Signal accepted for asynchronous persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true,"id":"evt_example"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/profiles":{"post":{"tags":["Ingestion"],"summary":"Ingest a runtime profile","description":"Track bounded CPU and memory profile summaries for Node.js routes, workers, jobs, and other runtime tasks.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfilePayload"},"examples":{"default":{"value":{"name":"worker.tick","kind":"cpu","runtime":"node","service":"worker","started_at":"2026-05-24T12:00:00.000Z","duration_ms":1000,"sample_count":5,"top_functions":[{"function_name":"tick","self_time_ms":25,"sample_count":5}],"source":"node","release":"2026.05.24"}}}}}},"responses":{"202":{"description":"Signal accepted for asynchronous persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true,"id":"evt_example"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/traces":{"post":{"tags":["Ingestion"],"summary":"Ingest a trace","description":"Track a top-level workflow trace.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TracePayload"},"examples":{"default":{"value":{"name":"generate_dashboard","status":"success","trace_id":"trace_dashboard_001"}}}}}},"responses":{"202":{"description":"Signal accepted for asynchronous persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true,"id":"evt_example"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/spans":{"post":{"tags":["Ingestion"],"summary":"Ingest a span","description":"Track a child operation within a trace.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpanPayload"},"examples":{"default":{"value":{"trace_id":"trace_dashboard_001","name":"llm_generate_sql","status":"success"}}}}}},"responses":{"202":{"description":"Signal accepted for asynchronous persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true,"id":"evt_example"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/identify/user":{"post":{"tags":["Ingestion"],"summary":"Identify a user","description":"Upsert user profile traits scoped to the ingestion API key. Traits shallow-merge into the existing profile. Call this after login/session load or whenever durable user traits change.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserIdentifyPayload"},"examples":{"default":{"value":{"user_id":"user_456","tenant_id":"tenant_123","traits":{"name":"Ana Souza","email":"ana@example.com","role":"admin","plan":"pro"}}}}}}},"responses":{"202":{"description":"Identify payload accepted for persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentifyAcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/identify/tenant":{"post":{"tags":["Ingestion"],"summary":"Identify a tenant","description":"Upsert tenant profile traits scoped to the ingestion API key. Traits shallow-merge into the existing profile. Call this after tenant/workspace selection or whenever durable tenant traits change.","security":[{"ingestionApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantIdentifyPayload"},"examples":{"default":{"value":{"tenant_id":"tenant_123","traits":{"name":"MicroERP","plan":"pro","operation_mode":"production"}}}}}}},"responses":{"202":{"description":"Identify payload accepted for persistence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentifyAcceptedResponse"},"examples":{"accepted":{"value":{"accepted":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/v1/source-maps":{"post":{"tags":["Source maps"],"summary":"Upload source maps from CI","description":"Upload a single `.map` file or zip bundle using a dedicated source-map upload token. Do not use browser ingestion keys for this endpoint.","security":[{"sourceMapUploadToken":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["project_id","environment_id","release"],"properties":{"project_id":{"type":"string"},"environment_id":{"type":"string"},"release":{"type":"string"},"minified_file":{"type":"string","description":"Required when uploading a single .map file. Omit for zip bundles."},"file":{"type":"string","format":"binary","description":"Single source-map file. Provide exactly one of file or bundle."},"bundle":{"type":"string","format":"binary","description":"Zip bundle containing one or more .map files. Provide exactly one of file or bundle."}},"anyOf":[{"required":["file","minified_file"]},{"required":["bundle"]}]}}}},"responses":{"201":{"description":"Source-map artifact uploaded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/heartbeats/{id}":{"post":{"tags":["Ingestion"],"summary":"Check in a heartbeat monitor","description":"Records a successful heartbeat check-in for scheduler, queue, cron, or background services.","security":[{"heartbeatSecret":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"202":{"description":"Heartbeat accepted","content":{"application/json":{"example":{"accepted":true}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Heartbeat monitor not found"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/admin/surveys":{"get":{"tags":["Session authenticated"],"summary":"List in-app surveys","description":"List active survey definitions for a project/environment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Survey definitions","content":{"application/json":{"schema":{"type":"object","properties":{"surveys":{"type":"array","items":{"$ref":"#/components/schemas/Survey"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Create an in-app survey","description":"Create a project/environment-scoped survey with targeting, optional trigger event, and one or more questions.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId","key","name","questions"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["draft","active","paused","archived"],"default":"draft"},"actorType":{"type":"string","enum":["user","tenant","session"],"default":"user"},"triggerEvent":{"type":["string","null"]},"questions":{"type":"array","items":{"$ref":"#/components/schemas/SurveyQuestion"}},"targeting":{"type":"object","additionalProperties":true}}},"examples":{"default":{"value":{"projectId":"prj_123","environmentId":"env_123","key":"activation_pulse","name":"Activation pulse","status":"active","actorType":"user","triggerEvent":"checkout.completed","questions":[{"id":"satisfaction","type":"rating","label":"How satisfied are you?","required":true,"scale":{"min":1,"max":5}}],"targeting":{"sampleRate":0.25}}}}}}},"responses":{"201":{"description":"Survey created","content":{"application/json":{"schema":{"type":"object","properties":{"survey":{"$ref":"#/components/schemas/Survey"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/surveys/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update an in-app survey","description":"Update mutable survey metadata, status, actor type, questions, trigger event, or targeting.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Survey updated","content":{"application/json":{"schema":{"type":"object","properties":{"survey":{"$ref":"#/components/schemas/Survey"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Survey not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive an in-app survey","description":"Soft-archive a survey definition so it no longer appears in active lists.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Survey archived"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/message-campaigns":{"get":{"tags":["Session authenticated"],"summary":"List message campaigns","description":"List active product messaging campaign definitions for a project/environment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Message campaign definitions","content":{"application/json":{"schema":{"type":"object","properties":{"campaigns":{"type":"array","items":{"$ref":"#/components/schemas/MessageCampaign"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Create a message campaign","description":"Create a scoped campaign definition for in-app, email, or webhook delivery. Email and webhook campaigns require an existing notification channel id. Campaigns are measured from campaign events and respect opt-out records.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId","key","name","body"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["draft","active","paused","archived"],"default":"draft"},"channelType":{"type":"string","enum":["email","webhook","in_app"],"default":"email"},"notificationChannelId":{"type":["string","null"]},"segmentId":{"type":["string","null"]},"conversionEvent":{"type":["string","null"]},"subject":{"type":["string","null"]},"body":{"type":"string"},"ctaUrl":{"type":["string","null"],"format":"uri"},"consentCategory":{"type":"string","default":"product"},"privacyNote":{"type":["string","null"]},"deliveryEnabled":{"type":"boolean","default":false,"description":"Deliver the campaign through Sigmon. Requires the `campaign_delivery` feature; e-mail then needs no notification channel."},"audienceType":{"type":"string","enum":["segment","all_identified"],"default":"segment"},"perUserCap":{"type":"integer","minimum":1,"maximum":100,"default":1}}},"examples":{"default":{"value":{"projectId":"prj_123","environmentId":"env_123","key":"invoice_activation","name":"Invoice activation","status":"active","channelType":"in_app","segmentId":"seg_123","conversionEvent":"invoice.paid","body":"Create your first invoice to finish onboarding.","consentCategory":"product"}}}}}},"responses":{"201":{"description":"Campaign created","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/MessageCampaign"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/message-campaigns/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update a message campaign","description":"Update mutable campaign metadata, status, channel linkage, target segment, copy, conversion event, consent category, or privacy note.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Campaign updated","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/MessageCampaign"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Campaign not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive a message campaign","description":"Soft-archive a campaign definition so it no longer appears in active lists.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Campaign archived"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/message-campaigns/{id}/preview":{"post":{"tags":["Session authenticated"],"summary":"Preview a campaign message","description":"Render the campaign for a real profile (`userId`) or sample data, with template variables substituted and the body HTML-escaped. Lists the variables the recipient has no value for. Sends nothing. Requires the `campaign_delivery` feature.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string"}}}}}},"responses":{"200":{"description":"Rendered message","content":{"application/json":{"schema":{"type":"object","properties":{"preview":{"$ref":"#/components/schemas/MessageCampaignPreview"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Campaign not found"},"409":{"description":"The campaign cannot be sent from its current state, or e-mail delivery is not configured (`smtp_not_configured`, `public_endpoint_missing`)"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/message-campaigns/{id}/test-send":{"post":{"tags":["Session authenticated"],"summary":"Send a test message to yourself","description":"Send the rendered e-mail campaign to the signed-in administrator's own address through the instance SMTP configuration. The recipient cannot be chosen. Requires the `campaign_delivery` feature.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Test message sent","content":{"application/json":{"schema":{"type":"object","properties":{"sent":{"type":"boolean"},"to":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Campaign not found"},"409":{"description":"The campaign cannot be sent from its current state, or e-mail delivery is not configured (`smtp_not_configured`, `public_endpoint_missing`)"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/message-campaigns/{id}/send":{"post":{"tags":["Session authenticated"],"summary":"Send a campaign now","description":"Schedule a delivery campaign for immediate delivery. The worker expands the audience once, then sends in rate-limited batches; a user is never sent the same campaign twice. Allowed from `none`, `scheduled` and `cancelled`. Requires the `campaign_delivery` feature.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Campaign updated","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/MessageCampaign"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Campaign not found"},"409":{"description":"The campaign cannot be sent from its current state, or e-mail delivery is not configured (`smtp_not_configured`, `public_endpoint_missing`)"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/message-campaigns/{id}/schedule":{"post":{"tags":["Session authenticated"],"summary":"Schedule a campaign","description":"Schedule a delivery campaign for `sendAt` (at most one year ahead; a past time sends now). Rescheduling replaces the time. Requires the `campaign_delivery` feature.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sendAt"],"properties":{"sendAt":{"type":"string","format":"date-time"}}}}}},"responses":{"200":{"description":"Campaign updated","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/MessageCampaign"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Campaign not found"},"409":{"description":"The campaign cannot be sent from its current state, or e-mail delivery is not configured (`smtp_not_configured`, `public_endpoint_missing`)"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/message-campaigns/{id}/cancel":{"post":{"tags":["Session authenticated"],"summary":"Cancel a campaign's delivery","description":"Stop a scheduled or sending campaign. Messages already sent stay sent; pending recipients are skipped. Requires the `campaign_delivery` feature.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Delivery cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/MessageCampaign"},"skipped":{"type":"integer"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Campaign not found"},"409":{"description":"The campaign cannot be sent from its current state, or e-mail delivery is not configured (`smtp_not_configured`, `public_endpoint_missing`)"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/message-campaign-settings":{"get":{"tags":["Session authenticated"],"summary":"Get campaign delivery settings","description":"Read the project's global frequency cap: deliveries one user may receive in any rolling 24 hours across all campaigns and channels (0 disables it, default 3). Requires the `campaign_delivery` feature.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Settings","content":{"application/json":{"schema":{"type":"object","properties":{"settings":{"type":"object","properties":{"dailyCapPerUser":{"type":"integer","minimum":0,"maximum":100}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"put":{"tags":["Session authenticated"],"summary":"Update campaign delivery settings","description":"Set the project's global per-user daily frequency cap. A delivery over the cap is skipped (never queued for later) and counted as skipped in the campaign results. Requires the `campaign_delivery` feature.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","dailyCapPerUser"],"properties":{"projectId":{"type":"string"},"dailyCapPerUser":{"type":"integer","minimum":0,"maximum":100}}}}}},"responses":{"200":{"description":"Settings updated"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/feedback-widget":{"get":{"tags":["Session authenticated"],"summary":"Get feedback widget settings","description":"Read project/environment feedback widget settings used by browser SDK installations.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Feedback widget settings","content":{"application/json":{"schema":{"type":"object","properties":{"settings":{"$ref":"#/components/schemas/FeedbackWidgetSettings"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"put":{"tags":["Session authenticated"],"summary":"Update feedback widget settings","description":"Enable/disable the browser feedback widget and update its copy and privacy note for one project environment.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId","enabled"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"enabled":{"type":"boolean"},"title":{"type":"string"},"prompt":{"type":"string"},"placeholder":{"type":"string"},"buttonLabel":{"type":"string"},"accentColor":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"allowScreenshot":{"type":"boolean","description":"Server-side switch for masked page snapshots (default false). Despite the name this never enables pixel screenshots; it allows `snapshot` payloads (serialised, masked DOM) on bug reports. The host app must also opt in with `captureSnapshot` in the SDK."},"privacyNote":{"type":["string","null"]}}}}}},"responses":{"200":{"description":"Feedback widget settings","content":{"application/json":{"schema":{"type":"object","properties":{"settings":{"$ref":"#/components/schemas/FeedbackWidgetSettings"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/feature-flags":{"get":{"tags":["Session authenticated"],"summary":"List feature flags","description":"List active feature flag definitions for a project/environment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Feature flags","content":{"application/json":{"schema":{"type":"object","properties":{"flags":{"type":"array","items":{"$ref":"#/components/schemas/FeatureFlag"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Create feature flag","description":"Create a project/environment-scoped feature flag with a safe default variant and ordered targeting rules.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId","key","name","defaultVariant","variants"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["draft","active","paused","archived"],"default":"draft"},"defaultVariant":{"type":"string"},"variants":{"type":"array","items":{"$ref":"#/components/schemas/FeatureFlagVariant"}},"rules":{"type":"array","items":{"$ref":"#/components/schemas/FeatureFlagRule"}}}},"examples":{"default":{"value":{"projectId":"prj_123","environmentId":"env_123","key":"new_checkout","name":"New checkout","status":"active","defaultVariant":"off","variants":[{"key":"off","value":false},{"key":"on","value":true}],"rules":[{"variant":"on","match":{"userId":"user_123"}}]}}}}}},"responses":{"201":{"description":"Feature flag created","content":{"application/json":{"schema":{"type":"object","properties":{"flag":{"$ref":"#/components/schemas/FeatureFlag"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/feature-flags/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update feature flag","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Feature flag updated","content":{"application/json":{"schema":{"type":"object","properties":{"flag":{"$ref":"#/components/schemas/FeatureFlag"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Feature flag not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive feature flag","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Feature flag archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/feature-flags/{id}/audit":{"get":{"tags":["Session authenticated"],"summary":"List feature flag audit history","description":"Returns created, updated, and archived audit entries for a feature flag.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Feature flag audit entries","content":{"application/json":{"schema":{"type":"object","properties":{"audit":{"type":"array","items":{"$ref":"#/components/schemas/FeatureFlagAudit"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"}},"/admin/feature-flags/{id}/evaluate":{"post":{"tags":["Session authenticated"],"summary":"Preview feature flag evaluation","description":"Evaluates a feature flag for a sample user, tenant, session, or trait context.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fallbackVariant":{"type":"string"},"subject":{"type":"object","properties":{"userId":{"type":"string"},"tenantId":{"type":"string"},"sessionId":{"type":"string"},"traits":{"type":"object","additionalProperties":true}}}}},"examples":{"default":{"value":{"fallbackVariant":"off","subject":{"userId":"user_123","traits":{"plan":"beta"}}}}}}}},"responses":{"200":{"description":"Feature flag evaluation","content":{"application/json":{"schema":{"type":"object","properties":{"evaluation":{"$ref":"#/components/schemas/FeatureFlagEvaluation"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/beta-programs":{"get":{"tags":["Session authenticated"],"summary":"List beta programs","description":"List early-access/beta programs for a project/environment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Beta programs","content":{"application/json":{"schema":{"type":"object","properties":{"programs":{"type":"array","items":{"$ref":"#/components/schemas/BetaProgram"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Create beta program","description":"Create an early-access cohort. When featureFlagId is set, active participants are synced into that flag as targeting rules.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId","key","name"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["draft","active","paused","archived"],"default":"draft"},"actorType":{"type":"string","enum":["user","tenant"],"default":"user"},"featureFlagId":{"type":["string","null"]},"featureFlagVariant":{"type":"string","default":"on"}}},"examples":{"default":{"value":{"projectId":"prj_123","environmentId":"env_123","key":"checkout_beta","name":"Checkout beta","status":"active","actorType":"user","featureFlagId":"flg_123","featureFlagVariant":"on"}}}}}},"responses":{"201":{"description":"Beta program created","content":{"application/json":{"schema":{"type":"object","properties":{"program":{"$ref":"#/components/schemas/BetaProgram"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/beta-programs/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update beta program","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Beta program updated","content":{"application/json":{"schema":{"type":"object","properties":{"program":{"$ref":"#/components/schemas/BetaProgram"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Beta program not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive beta program","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Beta program archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/beta-programs/{id}/participants":{"get":{"tags":["Session authenticated"],"summary":"List beta program participants","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Participants","content":{"application/json":{"schema":{"type":"object","properties":{"participants":{"type":"array","items":{"$ref":"#/components/schemas/BetaProgramParticipant"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"post":{"tags":["Session authenticated"],"summary":"Add beta program participant","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId","actorId"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"actorType":{"type":"string","enum":["user","tenant"],"default":"user"},"actorId":{"type":"string"},"status":{"type":"string","enum":["invited","active","opted_out","removed"],"default":"active"},"notes":{"type":["string","null"]}}}}}},"responses":{"201":{"description":"Participant added","content":{"application/json":{"schema":{"type":"object","properties":{"participant":{"$ref":"#/components/schemas/BetaProgramParticipant"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/beta-programs/{id}/participants/{participantId}":{"delete":{"tags":["Session authenticated"],"summary":"Remove beta program participant","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"participantId","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Participant removed"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/beta-programs/{id}/adoption":{"get":{"tags":["Session authenticated"],"summary":"Read beta program adoption","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"]}}],"responses":{"200":{"description":"Adoption summary","content":{"application/json":{"schema":{"type":"object","properties":{"adoption":{"$ref":"#/components/schemas/BetaProgramAdoption"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"}},"/admin/data-governance":{"get":{"tags":["Session authenticated"],"summary":"Read data governance policy","description":"Read scoped retention overrides and sensitive property rules for a project/environment. Categories absent from the policy use installation defaults.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Data governance policy","content":{"application/json":{"schema":{"type":"object","properties":{"policy":{"$ref":"#/components/schemas/DataGovernancePolicy"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"put":{"tags":["Session authenticated"],"summary":"Update data governance policy","description":"Configure project/environment retention values that override installation defaults whether shorter or longer, plus property mask/block rules.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"retentionPolicy":{"type":"object","description":"Closed per-category project/environment overrides in days. Omitted categories use their corresponding installation defaults; clicks, replays, and webVitals inherit RETENTION_EVENTS_DAYS. Unknown categories are rejected.","properties":{"events":{"type":"integer","minimum":1,"maximum":3650},"errors":{"type":"integer","minimum":1,"maximum":3650},"traces":{"type":"integer","minimum":1,"maximum":3650},"spans":{"type":"integer","minimum":1,"maximum":3650},"llmCalls":{"type":"integer","minimum":1,"maximum":3650},"profiles":{"type":"integer","minimum":1,"maximum":3650},"breadcrumbs":{"type":"integer","minimum":1,"maximum":3650},"webVitals":{"type":"integer","minimum":1,"maximum":3650},"clicks":{"type":"integer","minimum":1,"maximum":3650},"replays":{"type":"integer","minimum":1,"maximum":3650}},"additionalProperties":false,"examples":[{"events":90,"errors":180,"traces":30}]},"propertyRules":{"type":"array","items":{"$ref":"#/components/schemas/DataGovernancePropertyRule"}}}}}}},"responses":{"200":{"description":"Data governance policy updated","content":{"application/json":{"schema":{"type":"object","properties":{"policy":{"$ref":"#/components/schemas/DataGovernancePolicy"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/projects/{projectId}/code-integrations":{"get":{"tags":["Session authenticated"],"summary":"List code hosting integrations","description":"List GitHub/GitLab repository links configured for a project. No provider token is stored by this MVP.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Code integrations","content":{"application/json":{"schema":{"type":"object","properties":{"integrations":{"type":"array","items":{"$ref":"#/components/schemas/CodeIntegration"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"post":{"tags":["Session authenticated"],"summary":"Connect a GitHub/GitLab repository","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["provider","name","owner","repo"],"properties":{"provider":{"type":"string","enum":["github","gitlab"]},"name":{"type":"string"},"owner":{"type":"string","examples":["acme","platform/team"]},"repo":{"type":"string","examples":["web"]}}}}}},"responses":{"201":{"description":"Code integration created","content":{"application/json":{"schema":{"type":"object","properties":{"integration":{"$ref":"#/components/schemas/CodeIntegration"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/projects/{projectId}/code-integrations/{id}":{"delete":{"tags":["Session authenticated"],"summary":"Disconnect a code hosting integration","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Code integration disconnected"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Code integration not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/projects/{projectId}/llm-price-overrides":{"get":{"tags":["Session authenticated"],"summary":"List LLM price overrides","description":"List the per-project LLM price table. When an LLM call arrives without `cost_usd`, the worker prices it from the matching override (newest `effectiveFrom` on or before the call timestamp) before consulting the built-in catalog, and stores `cost_source = project_override`. A cost sent by the client is never overridden.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Price overrides, ordered by provider, model and newest effective date","content":{"application/json":{"schema":{"type":"object","required":["overrides"],"properties":{"overrides":{"type":"array","items":{"$ref":"#/components/schemas/LlmPriceOverride"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Price override repository unavailable in this deployment"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"put":{"tags":["Session authenticated"],"summary":"Create or update an LLM price override","description":"Upsert a price keyed by project, normalised provider, normalised model and `effectiveFrom`. Saving the same key edits that version; a later `effectiveFrom` adds a new version and leaves earlier calls priced as before. Already stored calls are not re-priced.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["provider","model","inputUsdPerMillion","outputUsdPerMillion","effectiveFrom"],"additionalProperties":false,"properties":{"provider":{"type":"string","minLength":1,"maxLength":128,"examples":["openai"]},"model":{"type":"string","minLength":1,"maxLength":256,"examples":["gpt-4o"]},"aliases":{"type":"array","maxItems":20,"items":{"type":"string","minLength":1,"maxLength":256}},"inputUsdPerMillion":{"type":"number","minimum":0,"maximum":1000000},"outputUsdPerMillion":{"type":"number","minimum":0,"maximum":1000000},"cachedInputUsdPerMillion":{"type":["number","null"],"minimum":0,"maximum":1000000},"effectiveFrom":{"type":"string","format":"date","examples":["2026-11-01"]}}}}}},"responses":{"200":{"description":"Saved override","content":{"application/json":{"schema":{"type":"object","required":["override"],"properties":{"override":{"$ref":"#/components/schemas/LlmPriceOverride"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Active project not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"501":{"description":"Price override repository unavailable in this deployment"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/projects/{projectId}/llm-price-overrides/{id}":{"delete":{"tags":["Session authenticated"],"summary":"Delete an LLM price override","description":"Remove one price version. Future un-costed calls fall back to the next matching override or the catalog; stored calls keep their cost.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Override deleted"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Override not found in this project"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"501":{"description":"Price override repository unavailable in this deployment"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/projects/{projectId}/release-metadata":{"post":{"tags":["Session authenticated"],"summary":"Upsert release code metadata","description":"Attach commit/PR/deployer metadata to a release so Overview can show deploy context.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["environmentId","release"],"properties":{"environmentId":{"type":"string"},"release":{"type":"string"},"integrationId":{"type":["string","null"]},"commitSha":{"type":["string","null"]},"commitUrl":{"type":["string","null"],"format":"uri"},"pullRequestNumber":{"type":["integer","null"]},"pullRequestUrl":{"type":["string","null"],"format":"uri"},"deployedBy":{"type":["string","null"]}}}}}},"responses":{"201":{"description":"Release metadata saved","content":{"application/json":{"schema":{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/ReleaseMetadata"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/warehouse-destinations":{"get":{"tags":["Session authenticated"],"summary":"List warehouse export destinations","description":"List project/environment destinations for incremental warehouse export. Raw connection URLs are never returned.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Warehouse destinations","content":{"application/json":{"schema":{"type":"object","properties":{"destinations":{"type":"array","items":{"$ref":"#/components/schemas/WarehouseDestination"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"post":{"tags":["Session authenticated"],"summary":"Create warehouse export destination","description":"Create a Postgres destination. The connection URL is write-only and stored for the scheduler.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId","name","connectionUrl","datasets"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"name":{"type":"string"},"destinationType":{"type":"string","enum":["postgres"],"default":"postgres"},"connectionUrl":{"type":"string","format":"uri"},"datasets":{"type":"array","minItems":1,"maxItems":6,"description":"Identity profile datasets export actor-id-ordered cyclic snapshots with scope-safe source ids. The cursor resets after a complete pass, so subsequent cycles re-export current profile state and pick up updates made behind an active cursor.","items":{"type":"string","enum":["events","errors","traces","llmCalls","userProfiles","tenantProfiles"]}},"batchSize":{"type":"integer","minimum":1,"maximum":5000,"default":500},"enabled":{"type":"boolean","default":true}}}}}},"responses":{"201":{"description":"Warehouse destination created","content":{"application/json":{"schema":{"type":"object","properties":{"destination":{"$ref":"#/components/schemas/WarehouseDestination"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/warehouse-destinations/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update warehouse export destination","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"name":{"type":"string"},"connectionUrl":{"type":"string","format":"uri"},"datasets":{"type":"array","minItems":1,"maxItems":6,"description":"Identity profile datasets export actor-id-ordered cyclic snapshots with scope-safe source ids. The cursor resets after a complete pass, so subsequent cycles re-export current profile state and pick up updates made behind an active cursor.","items":{"type":"string","enum":["events","errors","traces","llmCalls","userProfiles","tenantProfiles"]}},"batchSize":{"type":"integer","minimum":1,"maximum":5000},"enabled":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Warehouse destination updated","content":{"application/json":{"schema":{"type":"object","properties":{"destination":{"$ref":"#/components/schemas/WarehouseDestination"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Warehouse destination not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive warehouse export destination","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Warehouse destination archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/warehouse-destinations/{id}/runs":{"get":{"tags":["Session authenticated"],"summary":"List warehouse export runs","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Warehouse export runs","content":{"application/json":{"schema":{"type":"object","properties":{"runs":{"type":"array","items":{"$ref":"#/components/schemas/WarehouseExportRun"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"post":{"tags":["Session authenticated"],"summary":"Run warehouse export now","description":"Trigger a manual incremental export for one destination.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId"],"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"}}}}}},"responses":{"202":{"description":"Warehouse export accepted"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/auth/login":{"post":{"tags":["Auth"],"summary":"Create a human session","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginPayload"},"examples":{"default":{"value":{"email":"admin@example.com","password":"replace-with-your-password"}}}}}},"responses":{"200":{"description":"Session cookie set and user returned"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/auth/me":{"get":{"tags":["Session authenticated"],"summary":"Read current session user","description":"Returns the logged-in user for the active session cookie, including `role` (`admin`, `member`, or `viewer`) and the derived `isAdmin`.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/auth/push-subscriptions":{"get":{"tags":["Session authenticated"],"summary":"List the caller's push devices","description":"Returns whether Web Push is configured on this instance, the VAPID public key the browser subscribes with, and the devices the signed-in user registered. Endpoints and keys are never returned.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Web Push availability and the caller's devices"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Register a push device","description":"Stores the browser's PushSubscription for the signed-in user; subscribing the same endpoint again refreshes it. Any signed-in user may register their own devices. The endpoint must be an HTTPS URL on a known push service (Google FCM, Mozilla, Apple, Windows). A Pro feature (`push_alerts`): answers 402 `feature_not_in_plan` otherwise, and 503 `web_push_not_configured` when the instance has no VAPID keys.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["endpoint","keys"],"additionalProperties":false,"properties":{"endpoint":{"type":"string","format":"uri","maxLength":2048},"keys":{"type":"object","required":["p256dh","auth"],"additionalProperties":false,"properties":{"p256dh":{"type":"string","writeOnly":true},"auth":{"type":"string","writeOnly":true}}},"deviceLabel":{"type":"string","minLength":1,"maxLength":64}}}}}},"responses":{"201":{"description":"Device registered"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"delete":{"tags":["Session authenticated"],"summary":"Unregister a push device by endpoint","description":"Removes the signed-in user's own subscription for the given endpoint. Idempotent, and never gated by plan so a device can always be cleaned up.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["endpoint"],"additionalProperties":false,"properties":{"endpoint":{"type":"string","maxLength":2048}}}}}},"responses":{"204":{"description":"Device unregistered"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"}},"/auth/push-subscriptions/{id}":{"delete":{"tags":["Session authenticated"],"summary":"Unregister a push device by id","description":"Removes one of the signed-in user's own devices.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Device unregistered"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Device not found for this user"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"}},"/admin/push-subscriptions":{"get":{"tags":["Session authenticated"],"summary":"List push recipients","description":"List every active console user with the number of devices they can be reached on, for choosing the users a push channel notifies.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/auth/logout":{"post":{"tags":["Auth"],"summary":"End the human session","description":"Clears the session cookie for the current operator. Always returns success, including when no session was active.","responses":{"200":{"description":"Session cookie cleared"}}}},"/auth/google":{"get":{"tags":["Auth"],"summary":"Start Google OAuth sign-in","description":"Redirects the browser to the Google OAuth consent screen and sets a short-lived, path-scoped OAuth state cookie used to validate `/auth/google/callback`. Disabled unless Google OAuth is configured. This is a browser redirect, not a JSON endpoint.","responses":{"302":{"description":"Redirect to the Google OAuth authorization URL","headers":{"Location":{"schema":{"type":"string","format":"uri"},"description":"Google OAuth authorization URL."}}},"404":{"description":"Google OAuth is disabled"},"501":{"description":"Google OAuth is not configured"}}}},"/auth/google/callback":{"get":{"tags":["Auth"],"summary":"Complete Google OAuth sign-in","description":"Validates the OAuth `state` cookie set by `/auth/google` against the `code`/`state` query parameters, exchanges the code, and creates a human session on success. Disabled unless Google OAuth is configured.","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string"}},{"name":"state","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Session cookie set and user returned"},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"description":"Authenticated Google account is not an allowed operator"},"404":{"description":"Google OAuth is disabled"},"501":{"description":"Google OAuth is not configured"},"503":{"description":"Google OAuth token exchange or sign-in failed"}}}},"/auth/sso/start":{"get":{"tags":["Auth"],"summary":"Start OIDC single sign-on","description":"Pro feature `sso`. Redirects the browser to the configured OpenID Connect provider (authorization code flow with PKCE S256, `state` and `nonce`) and sets a short-lived, signed, HttpOnly flow cookie scoped to `/auth/sso/callback`. This is a browser redirect, not a JSON endpoint. If the provider cannot be reached the browser is redirected to `/console/?sso_error=sso_provider_unavailable`.","responses":{"302":{"description":"Redirect to the provider's authorization endpoint","headers":{"Location":{"schema":{"type":"string","format":"uri"},"description":"Provider authorization URL."}}},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"404":{"description":"SSO is not enabled"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"description":"SSO is not configured, or no callback URL is configured"}}}},"/auth/sso/callback":{"get":{"tags":["Auth"],"summary":"Complete OIDC single sign-on","description":"Pro feature `sso`. Validates the flow cookie against the `state` query parameter, exchanges the code (PKCE), verifies the id_token signature, issuer, audience, expiry and nonce, and requires a verified email. Maps the user by verified email: an existing local account is linked, otherwise a non-admin account is created when `jitProvisioning` is on and the email domain is allowed. SSO never grants admin. Always answers with a redirect: to `/console/` with the session cookie set on success, or to `/console/?sso_error=<code>` on failure (`sso_provider_denied`, `sso_invalid_callback`, `sso_state_mismatch`, `sso_token_invalid`, `sso_provider_unavailable`, `sso_email_missing`, `sso_email_not_verified`, `sso_domain_not_allowed`, `sso_user_not_provisioned`, `sso_identity_conflict`).","parameters":[{"name":"code","in":"query","required":false,"schema":{"type":"string"}},{"name":"state","in":"query","required":false,"schema":{"type":"string"}},{"name":"error","in":"query","required":false,"schema":{"type":"string"},"description":"Set by the provider when the user denied access."}],"responses":{"302":{"description":"Redirect to the console, with a session cookie on success or an `sso_error` code on failure"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"404":{"description":"SSO is not enabled"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"description":"SSO is not configured"}}}},"/admin/sso":{"get":{"tags":["Session authenticated"],"summary":"Read SSO settings","description":"Pro feature `sso`. Returns the effective OIDC configuration (database settings, or the `SSO_OIDC_*` environment fallback), the callback URL to register with the provider and the break-glass admin address. The client secret is write-only: only `clientSecretSet` is returned.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Effective SSO settings, without the client secret"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"put":{"tags":["Session authenticated"],"summary":"Update SSO settings","description":"Pro feature `sso`. Partial update of the database-stored OIDC configuration. `clientSecret` is write-only and encrypted at rest (requires `DATA_ENCRYPTION_KEY`; otherwise 409 `sso_secret_storage_unavailable`). Errors: 400 `sso_config_incomplete`, `sso_invalid_issuer` (HTTPS and outbound policy), `sso_invalid_domain`, `sso_jit_requires_domains`; 409 `sso_break_glass_unavailable` when `requireSso` is set but no active admin matches the break-glass address, and 409 `sso_break_glass_no_password` when that admin has no password to sign in with.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"issuer":{"type":"string","format":"uri","example":"https://accounts.google.com"},"clientId":{"type":"string"},"clientSecret":{"type":"string","writeOnly":true,"description":"Never returned by any route."},"tokenAuthMethod":{"type":"string","enum":["basic","post"],"nullable":true,"description":"Token endpoint client authentication (`client_secret_basic` or `client_secret_post`). Null or omitted follows the provider's discovery document, preferring basic."},"allowedDomains":{"type":"array","items":{"type":"string"},"example":["example.com"]},"requireSso":{"type":"boolean","description":"Close password sign-in for everyone except the break-glass admin."},"jitProvisioning":{"type":"boolean","description":"Create a user on first SSO sign-in. Created users are always non-admin and have no password (SSO never grants admin); false means invite-only, and unknown emails are rejected with `sso_user_not_provisioned`. Requires a non-empty `allowedDomains` (400 `sso_jit_requires_domains`). Existing accounts matched by verified email keep their role either way."}}}}}},"responses":{"200":{"description":"Updated SSO settings, without the client secret"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"description":"Client secret storage or the break-glass admin is unavailable"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/sso/test":{"post":{"tags":["Session authenticated"],"summary":"Test the SSO provider connection","description":"Pro feature `sso`. Runs OIDC discovery and fetches the provider's JWKS using the saved configuration, optionally overlaid with unsaved form values. Returns `{ result: { ok, ... } }` with a coarse `reason` on failure; the client secret is never echoed.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"issuer":{"type":"string","format":"uri"},"clientId":{"type":"string"},"clientSecret":{"type":"string","writeOnly":true}}}}}},"responses":{"200":{"description":"Test outcome (also returned with `ok: false` when the provider check fails)"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/analytics-segments":{"get":{"tags":["Session authenticated"],"summary":"List analytics segments","description":"List saved user or tenant segments for one project/environment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Create an analytics segment","description":"Create a validated saved segment for reuse across analytics views.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId","name","actorType","definition"],"additionalProperties":false,"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":256},"description":{"type":["string","null"],"maxLength":1024},"actorType":{"type":"string","enum":["user","tenant"]},"definition":{"description":"Saved user/tenant segment definition. Version 2 definitions use a recursive group/leaf expression tree; legacy definitions use event/property filters.","oneOf":[{"type":"object","required":["version","root"],"properties":{"version":{"type":"integer","const":2},"window":{"type":"string","enum":["24h","7d","30d"]},"root":{"$ref":"#/components/schemas/AnalyticsSegmentNode"}}},{"type":"object","anyOf":[{"required":["eventName"]},{"required":["propertyName"]}],"dependentRequired":{"propertyValue":["propertyName"]},"additionalProperties":false,"properties":{"window":{"type":"string","enum":["24h","7d","30d"],"default":"30d"},"eventName":{"type":"string","maxLength":256},"propertyName":{"type":"string","maxLength":128},"propertyValue":{"type":"string","maxLength":512}}}]}}}}}},"responses":{"201":{"description":"Analytics segment created"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/analytics-segments/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update an analytics segment","description":"Update the name, description, actor type, or validated definition of a saved segment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","minProperties":1,"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256},"description":{"type":["string","null"],"maxLength":1024},"actorType":{"type":"string","enum":["user","tenant"]},"definition":{"description":"Saved user/tenant segment definition. Version 2 definitions use a recursive group/leaf expression tree; legacy definitions use event/property filters.","oneOf":[{"type":"object","required":["version","root"],"properties":{"version":{"type":"integer","const":2},"window":{"type":"string","enum":["24h","7d","30d"]},"root":{"$ref":"#/components/schemas/AnalyticsSegmentNode"}}},{"type":"object","anyOf":[{"required":["eventName"]},{"required":["propertyName"]}],"dependentRequired":{"propertyValue":["propertyName"]},"additionalProperties":false,"properties":{"window":{"type":"string","enum":["24h","7d","30d"],"default":"30d"},"eventName":{"type":"string","maxLength":256},"propertyName":{"type":"string","maxLength":128},"propertyValue":{"type":"string","maxLength":512}}}]}}}}}},"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Analytics segment not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive an analytics segment","description":"Archive a saved analytics segment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Analytics segment archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/analytics-segments/{id}/preview":{"get":{"tags":["Session authenticated"],"summary":"Preview an analytics segment","description":"Return a bounded sample of actors matching a saved segment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Analytics segment not found"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"}},"/admin/experiments":{"get":{"tags":["Session authenticated"],"summary":"List experiments","description":"List experiments for one project/environment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Create an experiment","description":"Create an experiment definition used with deterministic SDK assignment and exposure/conversion telemetry.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId","key","name","conversionEvent","variants","primaryMetric"],"additionalProperties":false,"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"key":{"type":"string","minLength":1,"maxLength":80},"name":{"type":"string","minLength":1,"maxLength":256},"description":{"type":["string","null"],"maxLength":1024},"status":{"type":"string","enum":["draft","running","paused","completed","archived"],"default":"draft"},"actorType":{"type":"string","enum":["user","tenant","session"],"default":"user"},"exposureEvent":{"type":"string","maxLength":256,"default":"sigmon.experiment.exposed"},"conversionEvent":{"type":"string","minLength":1,"maxLength":256},"variants":{"type":"array","minItems":2,"maxItems":20,"items":{"type":"object","required":["key","name","weight"],"properties":{"key":{"type":"string","maxLength":80},"name":{"type":"string","maxLength":120},"weight":{"type":"integer","minimum":0,"maximum":100}}}},"primaryMetric":{"type":"object","required":["eventName"],"properties":{"eventName":{"type":"string","maxLength":256},"windowHours":{"type":"integer","minimum":1,"maximum":720,"default":24}}}}}}}},"responses":{"201":{"description":"Experiment created"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/experiments/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update an experiment","description":"Update an experiment within its project/environment scope.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","minProperties":1,"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256},"description":{"type":["string","null"],"maxLength":1024},"status":{"type":"string","enum":["draft","running","paused","completed","archived"],"default":"draft"},"actorType":{"type":"string","enum":["user","tenant","session"],"default":"user"},"exposureEvent":{"type":"string","maxLength":256,"default":"sigmon.experiment.exposed"},"conversionEvent":{"type":"string","minLength":1,"maxLength":256},"variants":{"type":"array","minItems":2,"maxItems":20,"items":{"type":"object","required":["key","name","weight"],"properties":{"key":{"type":"string","maxLength":80},"name":{"type":"string","maxLength":120},"weight":{"type":"integer","minimum":0,"maximum":100}}}},"primaryMetric":{"type":"object","required":["eventName"],"properties":{"eventName":{"type":"string","maxLength":256},"windowHours":{"type":"integer","minimum":1,"maximum":720,"default":24}}}}}}}},"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Experiment not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive an experiment","description":"Archive an experiment within its project/environment scope.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Experiment archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/source-maps":{"get":{"tags":["Session authenticated"],"summary":"List source-map artifacts","description":"List uploaded source-map artifacts for one project/environment, optionally filtered by release and paginated by cursor.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"release","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Upload source maps as an administrator","description":"Upload one source map or a bundle using the administrator session. Single-map uploads require `file` and `minified_file`; bundles require `bundle`.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["project_id","environment_id","release"],"properties":{"project_id":{"type":"string"},"environment_id":{"type":"string"},"release":{"type":"string"},"minified_file":{"type":"string"},"file":{"type":"string","format":"binary"},"bundle":{"type":"string","format":"binary"}},"oneOf":[{"required":["file","minified_file"]},{"required":["bundle"]}]}}}},"responses":{"200":{"description":"Source-map artifacts uploaded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project or environment scope not found or archived"},"413":{"description":"Compressed upload, expanded archive, or archive entry count exceeds the configured limit"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/source-maps/{id}":{"delete":{"tags":["Session authenticated"],"summary":"Delete a source-map artifact","description":"Delete one artifact within its project/environment scope.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Source-map artifact deleted"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/notification-channels":{"get":{"tags":["Session authenticated"],"summary":"List notification channels","description":"List redacted email, webhook, Slack, Discord, Telegram, WhatsApp, and push notification channels.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"post":{"tags":["Session authenticated"],"summary":"Create a notification channel","description":"Create an email, outbound webhook-compatible, WhatsApp, or push notification channel. Secret header values are write-only. WhatsApp and push channels are Pro features and answer 402 `feature_not_in_plan` when the edition does not include them.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["name","type","url"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256},"enabled":{"type":"boolean","default":true},"type":{"type":"string","const":"webhook"},"url":{"type":"string","format":"uri"},"secretHeaderName":{"type":["string","null"],"minLength":1,"maxLength":128},"secretHeaderValue":{"type":["string","null"],"minLength":1,"maxLength":4096,"writeOnly":true}}},{"type":"object","required":["name","type","url"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256},"enabled":{"type":"boolean","default":true},"type":{"type":"string","const":"slack"},"url":{"type":"string","format":"uri"},"secretHeaderName":{"type":["string","null"],"minLength":1,"maxLength":128},"secretHeaderValue":{"type":["string","null"],"minLength":1,"maxLength":4096,"writeOnly":true}}},{"type":"object","required":["name","type","url"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256},"enabled":{"type":"boolean","default":true},"type":{"type":"string","const":"discord"},"url":{"type":"string","format":"uri"},"secretHeaderName":{"type":["string","null"],"minLength":1,"maxLength":128},"secretHeaderValue":{"type":["string","null"],"minLength":1,"maxLength":4096,"writeOnly":true}}},{"type":"object","required":["name","type","url","telegramChatId"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256},"enabled":{"type":"boolean","default":true},"type":{"type":"string","const":"telegram"},"url":{"type":"string","format":"uri","description":"Bot sendMessage endpoint, https://api.telegram.org/bot<token>/sendMessage. Stored encrypted and never returned; the token is the credential, so HTTPS is required."},"telegramChatId":{"type":"string","minLength":1,"maxLength":64,"pattern":"^(-?\\d+|@[A-Za-z][A-Za-z0-9_]{4,31})$","description":"Target chat: a numeric id (negative for groups and supergroups) or an @channelusername."}}},{"type":"object","required":["name","type","emailRecipients"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256},"enabled":{"type":"boolean","default":true},"type":{"type":"string","const":"email"},"emailRecipients":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string","format":"email"}}}},{"type":"object","required":["name","type","whatsappPhone"],"additionalProperties":false,"description":"Pro (`whatsapp_alerts`). Answers 402 `feature_not_in_plan` on editions without it.","properties":{"name":{"type":"string","minLength":1,"maxLength":256},"enabled":{"type":"boolean","default":true},"type":{"type":"string","const":"whatsapp"},"whatsappPhone":{"type":"string","pattern":"^\\+[1-9][0-9]{6,14}$","description":"Recipient in E.164 format. Messages are sent through the instance's WhatsApp Business Cloud API credentials (environment), as an approved template."}}},{"type":"object","required":["name","type","pushUserIds"],"additionalProperties":false,"description":"Pro (`push_alerts`). Answers 402 `feature_not_in_plan` on editions without it.","properties":{"name":{"type":"string","minLength":1,"maxLength":256},"enabled":{"type":"boolean","default":true},"type":{"type":"string","const":"push"},"pushUserIds":{"type":"array","minItems":1,"maxItems":50,"uniqueItems":true,"items":{"type":"string"},"description":"Console user ids. The alert is pushed to every device each of them enabled notifications on."}}}]}}}},"responses":{"201":{"description":"Notification channel created"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/notification-channels/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update a notification channel","description":"Update a notification channel. Omitted secrets remain unchanged; clearing a secret header also clears its value. Editing a WhatsApp or push channel answers 402 `feature_not_in_plan` when the edition does not include it; archiving is never gated.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","minProperties":1,"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256},"enabled":{"type":"boolean","default":true},"type":{"type":"string","enum":["webhook","slack","discord","telegram","email","whatsapp","push"]},"url":{"type":["string","null"],"format":"uri"},"whatsappPhone":{"type":["string","null"],"pattern":"^\\+[1-9][0-9]{6,14}$"},"pushUserIds":{"type":"array","minItems":1,"maxItems":50,"uniqueItems":true,"items":{"type":"string"}},"emailRecipients":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string","format":"email"}},"secretHeaderName":{"type":["string","null"],"minLength":1,"maxLength":128},"secretHeaderValue":{"type":["string","null"],"minLength":1,"maxLength":4096,"writeOnly":true},"telegramChatId":{"type":["string","null"],"minLength":1,"maxLength":64,"pattern":"^(-?\\d+|@[A-Za-z][A-Za-z0-9_]{4,31})$"}}}}}},"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Notification channel not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive a notification channel","description":"Archive a notification channel.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Notification channel archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/alert-rules":{"get":{"tags":["Session authenticated"],"summary":"List alert rules","description":"List alert rules, optionally filtered by project and environment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Create an alert rule","description":"Create a threshold alert rule and optionally attach notification and escalation channels.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId","name","type","severity","windowMinutes","threshold","cooldownMinutes"],"additionalProperties":false,"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"notificationChannelId":{"type":["string","null"]},"escalationChannelId":{"type":["string","null"]},"name":{"type":"string","minLength":1,"maxLength":256},"type":{"type":"string","enum":["critical_errors","error_count","error_rate","trace_p95_latency","llm_cost","dead_letter_count"]},"severity":{"type":"string","enum":["info","warning","critical"]},"windowMinutes":{"type":"integer","minimum":1},"threshold":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$"},"cooldownMinutes":{"type":"integer","minimum":1},"escalationMinutes":{"type":["integer","null"],"minimum":1},"routePattern":{"type":["string","null"],"maxLength":256},"minimumSampleSize":{"type":"integer","minimum":1,"default":1},"enabled":{"type":"boolean","default":true}}}}}},"responses":{"201":{"description":"Alert rule created"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Scope or notification channel not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/alert-rules/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update an alert rule","description":"Update a threshold, routing, severity, status, or scope for an alert rule.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","minProperties":1,"additionalProperties":false,"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"notificationChannelId":{"type":["string","null"]},"escalationChannelId":{"type":["string","null"]},"name":{"type":"string","minLength":1,"maxLength":256},"type":{"type":"string","enum":["critical_errors","error_count","error_rate","trace_p95_latency","llm_cost","dead_letter_count"]},"severity":{"type":"string","enum":["info","warning","critical"]},"windowMinutes":{"type":"integer","minimum":1},"threshold":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$"},"cooldownMinutes":{"type":"integer","minimum":1},"escalationMinutes":{"type":["integer","null"],"minimum":1},"routePattern":{"type":["string","null"],"maxLength":256},"minimumSampleSize":{"type":"integer","minimum":1,"default":1},"enabled":{"type":"boolean","default":true}}}}}},"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Alert rule, scope, or notification channel not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive an alert rule","description":"Archive an alert rule.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Alert rule archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/users":{"get":{"tags":["Session authenticated"],"summary":"List console users","description":"List active console users. Each user carries `role` (`admin`, `member`, or `viewer`) and the derived `isAdmin`.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"post":{"tags":["Session authenticated"],"summary":"Create a console user","description":"Create a console user with an email address, password, and role. Omitting both `role` and `isAdmin` creates an admin, as before roles existed.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"additionalProperties":false,"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":12,"maxLength":256,"writeOnly":true},"role":{"type":"string","enum":["admin","member","viewer"],"description":"`admin` manages everything, `member` triages telemetry, `viewer` is read-only. Wins over `isAdmin`."},"isAdmin":{"type":"boolean","description":"Legacy: `true` means admin, `false` means viewer. Ignored when `role` is sent."}}}}}},"responses":{"201":{"description":"Console user created"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/users/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update a console user","description":"Change a console user's email, password, or role. Demoting the current user or the last active admin is refused.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","minProperties":1,"additionalProperties":false,"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":12,"maxLength":256,"writeOnly":true},"role":{"type":"string","enum":["admin","member","viewer"]},"isAdmin":{"type":"boolean","description":"Legacy: `true` means admin, `false` means viewer. Ignored when `role` is sent."}}}}}},"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"User not found"},"409":{"description":"The update would demote the current or last active administrator"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive a console user","description":"Archive an administrator. The current or last active administrator cannot be archived.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Console user archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"description":"The current or last active administrator cannot be archived"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/projects":{"get":{"tags":["Session authenticated"],"summary":"List projects","description":"List active SignalMonitor projects.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Create a project","description":"Create a SignalMonitor project.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256}}}}}},"responses":{"201":{"description":"Project created"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/projects/{id}":{"get":{"tags":["Session authenticated"],"summary":"Read a project","description":"Read one active SignalMonitor project.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project not found"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"patch":{"tags":["Session authenticated"],"summary":"Update a project","description":"Rename an active SignalMonitor project.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256}}}}}},"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive a project","description":"Archive a project and invalidate its browser-origin cache entries.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Project archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/projects/{projectId}/nav-pins":{"get":{"tags":["Session authenticated"],"summary":"Get pinned console navigation","description":"Return the calling console user's pinned navigation sections for a project (null when never saved) plus a suggested set derived from signals the project received in the last 30 days.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Pinned sections and suggestion"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project not found"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"put":{"tags":["Session authenticated"],"summary":"Save pinned console navigation","description":"Replace the calling console user's ordered pinned navigation sections for a project. Unknown or duplicate section ids are rejected; instance sections cannot be pinned.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["pins"],"additionalProperties":false,"properties":{"pins":{"type":"array","maxItems":15,"uniqueItems":true,"items":{"type":"string","enum":["overview","incidents","monitors","alerts","investigate","events","traces","llm","releases","analytics","users","entities","experiments","settings","installation"]}}}}}}},"responses":{"200":{"description":"Pinned sections saved"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"}},"/admin/projects/{projectId}/browser-origins":{"get":{"tags":["Session authenticated"],"summary":"List browser origins","description":"List browser origins allowed to send telemetry for a project.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"post":{"tags":["Session authenticated"],"summary":"Allow a browser origin","description":"Allow an absolute HTTP or HTTPS origin to use browser-scoped ingestion keys for a project.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["origin"],"additionalProperties":false,"properties":{"origin":{"type":"string","format":"uri","maxLength":2048,"examples":["https://app.example.com"]}}}}}},"responses":{"201":{"description":"Browser origin allowed"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/browser-origins/{id}":{"delete":{"tags":["Session authenticated"],"summary":"Archive a browser origin","description":"Remove a project browser origin from the runtime allowlist.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Browser origin archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/projects/{projectId}/environments":{"get":{"tags":["Session authenticated"],"summary":"List environments","description":"List active environments under a project.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Create an environment","description":"Create an environment under a project.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256}}}}}},"responses":{"201":{"description":"Environment created"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/environments/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update an environment","description":"Rename an active environment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256}}}}}},"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Environment not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive an environment","description":"Archive an environment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Environment archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/projects/{projectId}/api-keys":{"get":{"tags":["Session authenticated"],"summary":"List ingestion API keys","description":"List redacted ingestion API key records for a project.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"post":{"tags":["Session authenticated"],"summary":"Create an ingestion API key","description":"Create a browser- or server-scoped ingestion key. The full secret is returned only once.","security":[{"sessionCookie":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["environmentId","name","capability"],"additionalProperties":false,"properties":{"environmentId":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":120},"capability":{"type":"string","enum":["browser","server"]}}}}}},"responses":{"201":{"description":"API key created; the secret is shown only in this response"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project or environment not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/api-keys/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Rename an ingestion API key","description":"Rename an ingestion key without exposing its secret or stored hash.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256}}}}}},"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"API key not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Revoke an ingestion API key","description":"Revoke an ingestion key immediately.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"API key revoked"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/source-map-upload-tokens":{"get":{"tags":["Session authenticated"],"summary":"List source-map upload tokens","description":"List redacted CI source-map upload tokens for one project/environment.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"post":{"tags":["Session authenticated"],"summary":"Create a source-map upload token","description":"Create a scoped CI upload token. The full secret is returned only once.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectId","environmentId","name"],"additionalProperties":false,"properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":256}}}}}},"responses":{"201":{"description":"Upload token created; the secret is shown only in this response"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project or environment not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/source-map-upload-tokens/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Rename a source-map upload token","description":"Rename a CI upload token within its project/environment scope.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":256}}}}}},"responses":{"200":{"description":"Request succeeded"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Source-map upload token not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Revoke a source-map upload token","description":"Revoke a CI upload token within its project/environment scope.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Source-map upload token revoked"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/read-tokens":{"get":{"tags":["Session authenticated"],"summary":"List read tokens","description":"Admin route for listing scoped, revocable read-only credentials for one project/environment. Never includes the secret or the stored hash.","security":[{"sessionCookie":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Read tokens for the requested scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadTokenListResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"post":{"tags":["Session authenticated"],"summary":"Create a read token","description":"Admin route that generates a scoped, revocable read-only credential and returns the full secret exactly once, in this response. It cannot be retrieved again — only the redacted record (`prefix`, no `secret`, no `hash`) is returned by list, rename, or revoke.","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReadTokenPayload"},"examples":{"default":{"value":{"projectId":"prj_example","environmentId":"env_example","name":"claude-desktop"}}}}}},"responses":{"201":{"description":"Read token created; `token.secret` is shown only in this response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadTokenCreateResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project/environment scope is archived or does not exist"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"501":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/read-tokens/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Rename a read token","description":"Admin route for renaming a read token within its project/environment scope. Never returns the secret or the stored hash.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateReadTokenPayload"},"examples":{"default":{"value":{"name":"claude-desktop"}}}}}},"responses":{"200":{"description":"Read token renamed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadTokenResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Read token not found in the requested scope"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"501":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Revoke a read token","description":"Admin route for revoking a read token within its project/environment scope.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Read token revoked"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"501":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/admin/monitors":{"get":{"tags":["Session authenticated"],"summary":"List monitors","description":"Admin route for listing HTTP and heartbeat monitors.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/admin/monitors/http":{"post":{"tags":["Session authenticated"],"summary":"Create an HTTP monitor","description":"Admin route for creating an uptime monitor.","security":[{"sessionCookie":[]}],"responses":{"201":{"description":"HTTP monitor created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpMonitorPayload"},"examples":{"default":{"value":{"projectId":"prj_example","environmentId":"env_example","name":"API health","url":"https://api.example.com/health"}}}}}},"x-required-role":"admin"}},"/admin/monitors/heartbeat":{"post":{"tags":["Session authenticated"],"summary":"Create a heartbeat monitor","description":"Admin route that returns the heartbeat secret one time.","security":[{"sessionCookie":[]}],"responses":{"201":{"description":"Heartbeat monitor created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeartbeatMonitorPayload"},"examples":{"default":{"value":{"projectId":"prj_example","environmentId":"env_example","name":"Queue worker heartbeat","expectedIntervalMinutes":5,"graceMinutes":2}}}}}},"x-required-role":"admin"}},"/admin/monitors/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update a monitor","description":"Admin route for changing monitor configuration.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive a monitor","description":"Admin route for archiving a monitor.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"admin"}},"/admin/monitors/{id}/checks":{"get":{"tags":["Session authenticated"],"summary":"List monitor checks","description":"Admin route for recent HTTP or heartbeat monitor check history.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Monitor id."},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"},"description":"Project scope for the monitor and cursor."},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"},"description":"Environment scope for the monitor and cursor."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor returned by the previous response. Cursors are bound to the monitor, project, and environment."}],"x-required-role":"viewer"}},"/admin/dead-letter-jobs":{"get":{"tags":["Session authenticated"],"summary":"List dead-letter jobs","description":"Admin route for inspecting sanitized jobs that failed permanently in workers.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Dead-letter jobs returned newest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeadLetterJobListResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor returned by the previous response."},{"name":"queue_name","in":"query","required":false,"schema":{"type":"string"},"description":"Exact queue name to inspect, for example `telemetry`."},{"name":"job_name","in":"query","required":false,"schema":{"type":"string"},"description":"Exact worker job name to inspect, for example `event`, `error`, or `trace`."},{"name":"error","in":"query","required":false,"schema":{"type":"string"},"description":"Case-insensitive substring search over the sanitized error message."},{"name":"created_from","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Inclusive lower bound for dead-letter creation time."},{"name":"created_to","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Inclusive upper bound for dead-letter creation time."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending"]},"description":"Current active dead-letter status. Historical replay/delete/expiration status is exposed through the job actions endpoint."}],"x-required-role":"admin"}},"/admin/dead-letter-jobs/{id}":{"get":{"tags":["Session authenticated"],"summary":"Get a dead-letter job","description":"Admin route for inspecting one sanitized permanently failed worker job.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Dead-letter job returned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeadLetterJobResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Dead-letter job not found"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Delete a dead-letter job","description":"Admin route for clearing a dead-letter job after inspection or manual remediation.","security":[{"sessionCookie":[]}],"responses":{"204":{"description":"Dead-letter job deleted"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Dead-letter job not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"x-required-role":"admin"}},"/admin/dead-letter-jobs/{id}/actions":{"get":{"tags":["Session authenticated"],"summary":"List dead-letter job actions","description":"Admin route for inspecting replay/delete audit actions for a dead-letter job id.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Dead-letter job actions returned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeadLetterJobActionsResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"x-required-role":"admin"}},"/admin/dead-letter-jobs/{id}/replay":{"post":{"tags":["Session authenticated"],"summary":"Replay a dead-letter job","description":"Admin route for re-enqueueing a sanitized telemetry dead-letter job and clearing it after the enqueue succeeds.","security":[{"sessionCookie":[]}],"responses":{"202":{"description":"Dead-letter job re-enqueued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeadLetterReplayResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Dead-letter job not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"x-required-role":"admin"}},"/query/me":{"get":{"tags":["Session authenticated"],"summary":"Introspect the calling principal","description":"Return the authenticated caller's principal kind: a session user, or a read token together with its scoped project_id/environment_id (IDs only, no name lookup). Useful for a caller that needs to know which project/environment a read token is bound to before issuing further /query/* reads.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Authenticated principal","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"oneOf":[{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["user"]}}},{"type":"object","required":["kind","projectId","environmentId"],"properties":{"kind":{"type":"string","enum":["read-token"]},"projectId":{"type":"string"},"environmentId":{"type":"string"}}}]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}},"x-required-role":"viewer"}},"/query/fleet":{"get":{"tags":["Session authenticated"],"summary":"Query fleet operations","description":"Read a cross-project operations rollup for the selected window. Project environment details are intentionally omitted from this response and can be loaded lazily from the project environments endpoint.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Fleet operations rollup","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["window","generatedAt","projects","rollup"],"properties":{"window":{"type":"string","enum":["24h","7d","30d"]},"generatedAt":{"type":"string","format":"date-time"},"projects":{"type":"array","items":{"type":"object","additionalProperties":true}},"rollup":{"type":"object","additionalProperties":true}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Read token is scoped to project/environment reads and cannot access fleet routes (`read_token_scope_insufficient`); also returned when the caller's console role is below `x-required-role`"},"501":{"description":"Fleet query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"24h"}}],"x-required-role":"viewer"}},"/query/fleet/summary":{"get":{"tags":["Session authenticated"],"summary":"Query fleet home summary","description":"Read the cross-project home in one call: fleet KPIs with sparkline and previous-period delta, a severity-ranked feed of items that need attention, and a project-by-signal health matrix. Uses each project's primary environment (`production`, else the lexically first), the same selection as `/query/fleet`. States are judged against each project's own previous period of the same length; signals never received are `not_instrumented`, never a zero. A read token gets the same shape narrowed to its own project and exactly its own environment (that environment replaces the primary one, event volume is that environment only, and `environmentStrategy` reports `token_environment`); it never sees other projects or sibling environments.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Fleet home summary","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["window","generatedAt","range","environmentStrategy","latestSignalAt","kpis","feed","matrix"],"properties":{"window":{"type":"string","enum":["24h","7d"]},"generatedAt":{"type":"string","format":"date-time"},"range":{"type":"object","required":["from","to"],"properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"environmentStrategy":{"type":"object","description":"Which environments each signal reads. Events are summed across every non-archived environment (as in the health rail); every other signal follows the project's primary environment. Both fields are `token_environment` when a read token narrowed the summary to its own environment.","required":["default","events"],"properties":{"default":{"type":"string","enum":["primary","token_environment"]},"events":{"type":"string","enum":["all_non_archived","token_environment"]}}},"latestSignalAt":{"type":"string","format":"date-time","nullable":true,"description":"Newest event, error, trace or LLM call received by any listed project, regardless of the window; null when nothing was ever received. When it is older than the window, the window is empty because ingestion paused or lags."},"kpis":{"type":"array","items":{"type":"object","required":["id","value","previous","delta","deltaPct","unit","trend","projectsReporting"],"properties":{"id":{"type":"string","enum":["openIncidents","errorRate","events","monitorsDown","aiSpend"]},"value":{"type":"number","nullable":true},"previous":{"type":"number","nullable":true},"delta":{"type":"number","nullable":true},"deltaPct":{"type":"number","nullable":true,"description":"Percent change against the previous period; null when the previous period is below the minimum baseline for the unit (FLEET_DELTA_MIN_BASELINE), so clients show the absolute change instead."},"unit":{"type":"string","enum":["count","percent","usd"]},"trend":{"type":"array","items":{"type":"number"}},"projectsReporting":{"type":"integer"}}}},"feed":{"type":"array","items":{"type":"object","required":["id","kind","severity","projectId","projectName","environmentId","environmentName","occurredAt","title","detail","link"],"properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["monitor_down","regression","new_error_group","recurring_error_group","llm_cost_spike","new_feedback"]},"severity":{"type":"string","enum":["critical","warning","info"]},"projectId":{"type":"string"},"projectName":{"type":"string"},"environmentId":{"type":"string"},"environmentName":{"type":"string"},"occurredAt":{"type":"string","format":"date-time"},"title":{"type":"string"},"detail":{"type":"string","nullable":true},"link":{"type":"object","required":["screen"],"properties":{"screen":{"type":"string","enum":["incidents","monitors","releases","llm","analytics"]},"groupId":{"type":"string"}}}}}},"matrix":{"type":"array","items":{"type":"object","required":["projectId","projectName","environmentId","environmentName","cells"],"properties":{"projectId":{"type":"string"},"projectName":{"type":"string"},"environmentId":{"type":"string"},"environmentName":{"type":"string"},"cells":{"type":"object","description":"Keyed by errors, latency, monitors, releases, ai and feedback.","additionalProperties":{"type":"object","required":["state","value","unit","reason"],"properties":{"state":{"type":"string","enum":["ok","attention","critical","not_instrumented"]},"value":{"type":"number","nullable":true},"unit":{"type":"string","enum":["count","ms","usd"]},"reason":{"type":"string","nullable":true}}}}}}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Fleet summary query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d"],"default":"24h"}}],"x-required-role":"viewer"}},"/query/fleet/projects/{id}/environments":{"get":{"tags":["Session authenticated"],"summary":"Query project fleet environments","description":"Lazily load environment-level operations status for one fleet project and window. A read token only sees its own project, narrowed to its own environment; any other project id answers `404 project_not_found`, the same as an unknown project.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Project environment operations status","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["projectId","envs"],"properties":{"projectId":{"type":"string"},"envs":{"type":"array","items":{"type":"object","required":["name","status","incidents","events"],"properties":{"name":{"type":"string"},"status":{"type":"string","enum":["ok","warning","critical"]},"incidents":{"type":"integer","minimum":0},"errorRatePercent":{"type":["number","null"]},"events":{"type":"integer","minimum":0},"note":{"type":["string","null"]}}}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project not found (or, for a read token, not the token's project)"},"501":{"description":"Fleet environment query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"24h"}}],"x-required-role":"viewer"}},"/query/error-groups":{"get":{"tags":["Session authenticated"],"summary":"List error groups","description":"List error groups for a project environment with cursor pagination, most recently seen first. Query with project_id, environment_id, and optional status, severity, fingerprint, tenant_id, user_id, release, from, to, limit=1..500 (default 50), and cursor from a previous page's response.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Paginated error groups","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ErrorGroupRecord"}},"cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Error group query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["open","investigating","resolved","ignored"]}},{"name":"severity","in":"query","required":false,"schema":{"type":"string"}},{"name":"fingerprint","in":"query","required":false,"schema":{"type":"string"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"release","in":"query","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/query/error-groups/{id}":{"get":{"tags":["Session authenticated"],"summary":"Query error-group detail","description":"Read one error group scoped to a project environment. Query with project_id and environment_id.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Error group detail","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ErrorGroupRecord"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Error group not found"},"501":{"description":"Error group query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"x-required-role":"viewer"},"patch":{"tags":["Session authenticated"],"summary":"Update error-group triage state","description":"Update one error group's status, priority, and/or assignee. At least one of `status`, `priority`, or `assignedToUserId` must be present in the body; `status`/`priority` are applied first, then assignment. Query with project_id and environment_id.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Updated error group","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ErrorGroupRecord"}}}}}},"400":{"description":"Invalid request body/query, or (when assigning) `user_not_found`/`user_archived` in the `error` field of the response body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Read token cannot perform mutations (`read_token_is_read_only`); also returned when the caller's console role is below `x-required-role`"},"404":{"description":"Error group not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"501":{"description":"Triage mutation is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorGroupTriagePatch"},"examples":{"default":{"value":{"status":"investigating","priority":"high"}}}}}},"x-required-role":"member"}},"/query/error-groups/{id}/errors":{"get":{"tags":["Session authenticated"],"summary":"List error-group occurrences","description":"List raw error occurrences for one error group using cursor pagination. Results remain scoped to the requested project and environment.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Paginated error-group occurrences","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Error occurrence query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/query/aggregates/traces":{"get":{"tags":["Session authenticated"],"summary":"Query trace aggregates","description":"Read the stable public trace aggregate contract for a project environment: total traces and average trace duration in milliseconds. Optional actor, session, trace, and date filters narrow the aggregate without changing its response fields.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Trace count and average duration","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["total","averageDurationMs"],"properties":{"total":{"type":"integer","minimum":0},"averageDurationMs":{"type":"number","minimum":0}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Trace aggregate query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"session_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"trace_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}}],"x-required-role":"viewer"}},"/query/aggregates/errors":{"get":{"tags":["Session authenticated"],"summary":"Query error aggregates","description":"Read the stable public error aggregate contract for a project environment: total error count and open (unresolved) count. Optional actor, session, trace, and date filters narrow the aggregate without changing its response fields.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Error count and open count","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["total","open"],"properties":{"total":{"type":"integer","minimum":0},"open":{"type":"integer","minimum":0}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Error aggregate query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"session_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"trace_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}}],"x-required-role":"viewer"}},"/query/aggregates/events":{"get":{"tags":["Session authenticated"],"summary":"Query event aggregates","description":"Read the stable public event aggregate contract for a project environment: total event count and a per-event-name breakdown. Optional event_name, event_id, segment_id, actor, session, trace, and date filters narrow the aggregate without changing its response fields.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Event count and per-name breakdown","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["total","byName"],"properties":{"total":{"type":"integer","minimum":0},"byName":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Event aggregate query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"session_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"trace_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"event_name","in":"query","required":false,"schema":{"type":"string"}},{"name":"event_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}}],"x-required-role":"viewer"}},"/query/aggregates/llm":{"get":{"tags":["Session authenticated"],"summary":"Query LLM aggregates","description":"Read the stable public LLM aggregate contract for a project environment: total call count, total input/output tokens, and total cost. Optional provider, model, prompt_name, status, actor, session, trace, and date filters narrow the aggregate without changing its response fields.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"LLM call count, token totals, and cost total","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["totalCalls","totalInputTokens","totalOutputTokens","totalCostUsd","estimatedCostUsd","unpricedCalls"],"properties":{"totalCalls":{"type":"integer","minimum":0},"totalInputTokens":{"type":"integer","minimum":0},"totalOutputTokens":{"type":"integer","minimum":0},"totalCostUsd":{"type":"string","description":"Decimal string, e.g. \"1.2345\"."},"estimatedCostUsd":{"type":"string","description":"Part of costUsd estimated by the worker from the LLM pricing catalog or a project price override (cost_source = catalog or project_override). Decimal string."},"unpricedCalls":{"type":"integer","minimum":0,"description":"Calls with no client cost and no catalog price (cost_source = unknown); they add 0 to totalCostUsd."}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"LLM aggregate query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"session_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"trace_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"provider","in":"query","required":false,"schema":{"type":"string"}},{"name":"model","in":"query","required":false,"schema":{"type":"string"}},{"name":"prompt_name","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}}],"x-required-role":"viewer"}},"/query/events":{"get":{"tags":["Session authenticated"],"summary":"Query events","description":"Read project/environment scoped raw event telemetry.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/overview":{"get":{"tags":["Session authenticated"],"summary":"Query project overview","description":"Read operational overview rollups for one project environment, plus a signals object (which signal types were ever received) and a sessions score ({ total, errored, slow, ok, slowThresholdMs } or null when the project never sent session_id). Query with project_id, environment_id, window=24h|7d|30d (default 24h), and optional release for exact deploy-version filtering.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/recent-activity":{"get":{"tags":["Session authenticated"],"summary":"Query recent activity","description":"Read one mixed, time-ordered activity feed across events, errors, traces, and LLM calls for one project environment. Query with project_id, environment_id, window=24h|7d|30d, optional release, and optional limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/releases":{"get":{"tags":["Session authenticated"],"summary":"Query releases","description":"List recently observed release values for one project environment, derived from events, errors, traces, and LLM calls. Query with project_id, environment_id, window=24h|7d|30d, and optional limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/releases/health":{"get":{"tags":["Session authenticated"],"summary":"Query release health","description":"Per-release health for one project environment, newest first seen first (first/last seen are bounded to the window). Returns sessions (distinct session_id), adoptionPct (share of all window sessions), errorFreeSessionsPct, errorsIntroduced (error groups first seen in the window whose first occurrence was in the release), totalErrors, p95TraceDurationMs, and feedbackCount. Any metric with no underlying signal is null, never 0; the response also carries a signals presence object. Query with project_id, environment_id, window=24h|7d|30d (default 24h), and optional limit (default 50). Responds 400 `invalid_query` for a missing scope id or unknown window, 501 when the query backend does not support it, and 503 when it is unavailable. A read token reads only its own project/environment, which replaces the query parameters.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/events/properties":{"get":{"tags":["Session authenticated"],"summary":"Query event property catalog","description":"Read observed custom event properties for a project environment, including frequency, event coverage, inferred JSON types, safe sample values, type conflicts, and similar property-name groups. Query with project_id, environment_id, window=24h|7d|30d, and optional limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/operations":{"get":{"tags":["Session authenticated"],"summary":"Query operations rollup","description":"Read a single-window operations rollup for one project environment: monitor status counts, alert rule/event summaries, telemetry health (windowed counts and `lastEventAt`/`lastErrorAt`/`lastTraceAt`, plus `lastSignalAt`, the newest event, error, trace or LLM call in scope regardless of the window), incident counts, recent monitors/alerts/incidents, detected anomalies, and a heuristic operational-risk prediction. Query with project_id, environment_id, and optional window=24h|7d|30d (default 24h).","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Operations rollup","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["window","generatedAt","scope","range","status","summary","recent"],"properties":{"window":{"type":"string","enum":["24h","7d","30d"]},"generatedAt":{"type":"string","format":"date-time"},"scope":{"type":"object","properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"}}},"range":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"status":{"type":"string","enum":["healthy","degraded","unhealthy","not_configured"]},"summary":{"type":"object","description":"Monitor, alert, telemetry, and incident count rollups.","additionalProperties":true},"recent":{"type":"object","description":"Recent monitors, alerts, and incidents (bounded lists).","additionalProperties":true},"anomalies":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Detected volume/rate/latency/cost anomalies for the window."},"predictions":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Heuristic-weighted operational-risk predictions."}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Operations query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"24h"}}],"x-required-role":"viewer"}},"/admin/analytics-dashboards":{"get":{"tags":["Session authenticated"],"summary":"List analytics dashboards","description":"List saved dashboards for one project environment.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Create an analytics dashboard","description":"Create a dashboard composed of operational, product, and saved-insight widgets.","security":[{"sessionCookie":[]}],"responses":{"201":{"description":"Analytics dashboard created"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsDashboardInput"},"examples":{"default":{"value":{"projectId":"prj_example","environmentId":"env_example","name":"Checkout operations","category":"operational","filters":{"window":"7d"},"widgets":[{"type":"insight","title":"Checkout starts","width":"full","options":{"insightId":"ins_example"}}]}}}}}},"x-required-role":"admin"}},"/admin/analytics-dashboards/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update an analytics dashboard","description":"Update dashboard metadata, supported window filter, or widget layout.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsDashboardPatch"}}}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive an analytics dashboard","description":"Archive a dashboard within its project/environment scope.","security":[{"sessionCookie":[]}],"responses":{"204":{"description":"Analytics dashboard archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Analytics dashboard not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"x-required-role":"admin"}},"/admin/analytics/insights":{"get":{"tags":["Session authenticated"],"summary":"List saved analytics insights","description":"List active saved trend definitions for one project environment.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Create an analytics insight","description":"Save a scoped event trend definition with hour/day buckets, count or unique-actor metrics, optional event name, promoted-property breakdown, and property filters.","security":[{"sessionCookie":[]}],"responses":{"201":{"description":"Analytics insight created"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsInsightInput"},"examples":{"default":{"value":{"projectId":"prj_example","environmentId":"env_example","name":"Checkout starts by plan","definition":{"bucket":"hour","metric":"count","eventName":"checkout.started","breakdownProperty":"plan"}}}}}}},"x-required-role":"admin"}},"/admin/analytics/insights/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Update an analytics insight","description":"Rename or replace a saved trend definition within its project/environment scope.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsInsightPatch"}}}},"x-required-role":"admin"},"delete":{"tags":["Session authenticated"],"summary":"Archive an analytics insight","description":"Archive a saved trend definition.","security":[{"sessionCookie":[]}],"responses":{"204":{"description":"Analytics insight archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Analytics insight not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"x-required-role":"admin"}},"/admin/analytics/promoted-properties":{"get":{"tags":["Session authenticated"],"summary":"List promoted event properties","description":"List event properties promoted for indexed analytics breakdowns, including index lifecycle state.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"x-required-role":"viewer"},"post":{"tags":["Session authenticated"],"summary":"Promote an event property","description":"Create or retry a scoped expression index for an event property used by saved trend breakdowns.","security":[{"sessionCookie":[]}],"responses":{"201":{"description":"Event property promoted and index prepared"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotedEventPropertyInput"},"examples":{"default":{"value":{"projectId":"prj_example","environmentId":"env_example","property":"plan","displayName":"Subscription plan"}}}}}},"x-required-role":"admin"}},"/admin/analytics/promoted-properties/{id}":{"delete":{"tags":["Session authenticated"],"summary":"Archive a promoted event property","description":"Remove a scoped property index when no active insight references it.","security":[{"sessionCookie":[]}],"responses":{"204":{"description":"Promoted event property archived"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Promoted event property not found"},"409":{"description":"Property is referenced by an active insight"},"423":{"$ref":"#/components/responses/InstanceReadOnly"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"x-required-role":"admin"}},"/query/analytics/trends":{"get":{"tags":["Session authenticated"],"summary":"Query an analytics trend","description":"Execute a saved insight with insight_id or an explicit trend definition. Use either insight_id or bucket plus metric.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"from","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"insight_id","in":"query","schema":{"type":"string"}},{"name":"bucket","in":"query","schema":{"type":"string","enum":["hour","day"]}},{"name":"metric","in":"query","schema":{"type":"string","enum":["count","unique_actors"]}},{"name":"event_name","in":"query","schema":{"type":"string"}},{"name":"breakdown_property","in":"query","schema":{"type":"string","pattern":"^[A-Za-z0-9_.:-]{1,64}$"}},{"name":"filters","in":"query","description":"JSON array with at most 12 exact/exists property filters.","schema":{"type":"string"}}],"x-required-role":"viewer"}},"/query/analytics/engagement":{"get":{"tags":["Session authenticated"],"summary":"Query time on site and engagement","description":"Session engagement derived from the browser SDK's `$pageview` and `$pageleave` events (@sigmon/sdk >= 0.4.0). Reports sessions with pageviews, median and mean engaged time per session (sum of `$pageleave.engaged_ms`, visible-tab time only), pages per session, and bounce rate (a session with exactly one pageview and under 10 seconds engaged; `bounceThresholdMs`), for the window and the equally long previous period. Engaged-time figures cover only sessions that reported a `$pageleave` (`engagedSessions`). When the environment has never received a `$pageview`, `instrumented` is false and `current`/`previous` are null: render 'not instrumented', not zero.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Engagement summary","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["window","generatedAt","scope","range","previousRange","bounceThresholdMs","instrumented","current","previous"],"properties":{"window":{"type":"string","enum":["24h","7d","30d"]},"generatedAt":{"type":"string","format":"date-time"},"scope":{"type":"object","properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"}}},"range":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"previousRange":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"bounceThresholdMs":{"type":"integer","minimum":0},"instrumented":{"type":"boolean"},"current":{"oneOf":[{"$ref":"#/components/schemas/EngagementMetrics"},{"type":"null"}]},"previous":{"oneOf":[{"$ref":"#/components/schemas/EngagementMetrics"},{"type":"null"}]}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project or environment is archived"},"501":{"description":"Engagement query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"24h"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"release","in":"query","required":false,"schema":{"type":"string"}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/query/analytics/pages":{"get":{"tags":["Session authenticated"],"summary":"Query top pages","description":"Top pages by path from `$pageview`/`$pageleave` events: views, unique sessions, median and mean engaged time per view, entries (first pageview of a session), exits (last pageview of a session), and exit rate. A view's engaged time comes from the `$pageleave` that follows it for the same session and path; views with no leave are excluded from engaged-time figures (`measuredViews`) and never counted as 0. `instrumented` is false when the environment has never received a `$pageview`.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Top pages","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["window","generatedAt","scope","range","instrumented","sort","totals","pages"],"properties":{"window":{"type":"string","enum":["24h","7d","30d"]},"generatedAt":{"type":"string","format":"date-time"},"scope":{"type":"object","properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"}}},"range":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"instrumented":{"type":"boolean"},"sort":{"type":"string","enum":["views","engaged","exits"]},"totals":{"type":"object","required":["views","paths"],"properties":{"views":{"type":"integer","minimum":0},"paths":{"type":"integer","minimum":0}}},"pages":{"type":"array","items":{"type":"object","required":["path","views","sessions","measuredViews","medianEngagedMs","meanEngagedMs","entries","exits","exitRate"],"properties":{"path":{"type":"string"},"views":{"type":"integer","minimum":0},"sessions":{"type":"integer","minimum":0},"measuredViews":{"type":"integer","minimum":0},"medianEngagedMs":{"type":["number","null"]},"meanEngagedMs":{"type":["number","null"]},"entries":{"type":"integer","minimum":0},"exits":{"type":"integer","minimum":0},"exitRate":{"type":"number","minimum":0,"maximum":1}}}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project or environment is archived"},"501":{"description":"Pages query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"24h"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["views","engaged","exits"],"default":"views"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"release","in":"query","required":false,"schema":{"type":"string"}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/query/sessions/{sessionId}/pages":{"get":{"tags":["Session authenticated"],"summary":"Query a session's page path","description":"The ordered pages one session visited, each `$pageview` paired with the `$pageleave` that followed it for the same path. `engagedMs` and `durationMs` are null when no leave was received (never 0). `id` matches the id of the corresponding event item in the session timeline.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Session page path","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["sessionId","scope","instrumented","totalEngagedMs","pages"],"properties":{"sessionId":{"type":"string"},"scope":{"type":"object","properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"}}},"instrumented":{"type":"boolean"},"totalEngagedMs":{"type":["number","null"]},"pages":{"type":"array","maxItems":500,"items":{"type":"object","required":["id","path","timestamp","navigation","referrerPath","referrerHost","title","engagedMs","durationMs"],"properties":{"id":{"type":"string"},"path":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"navigation":{"type":["string","null"]},"referrerPath":{"type":["string","null"]},"referrerHost":{"type":["string","null"]},"title":{"type":["string","null"]},"engagedMs":{"type":["number","null"]},"durationMs":{"type":["number","null"]}}}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Project or environment is archived"},"501":{"description":"Session pages query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/query/reports/dashboards/{id}":{"get":{"tags":["Session authenticated"],"summary":"Render a saved analytics dashboard","description":"Evaluate every dashboard widget for one project environment. Insight widget failures are isolated and returned on that widget instead of failing the full report.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/query/events/funnel":{"get":{"tags":["Session authenticated"],"summary":"Query event conversion funnel","description":"Analyze ordered event-step conversion for a project environment, aggregated entirely in SQL. Query with project_id, environment_id, window=24h|7d|30d, steps as a comma-separated list of 2-12 event names, and optional limit for sample actors. Optional conversion_window (e.g. 30m, 24h, 7d) bounds elapsed time from funnel entry to each step. Optional breakdown_property splits results into up to 20 series by an event property value. Optional tenant_id and segment_id further scope which actors are counted.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/experiments/{id}/results":{"get":{"tags":["Session authenticated"],"summary":"Query experiment results","description":"Read A/B experiment conversion results by variant. Query with project_id, environment_id, window=24h|7d|30d, and optional limit. Results are derived from exposure and conversion events that include experiment_key and variant properties.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/surveys/{id}/results":{"get":{"tags":["Session authenticated"],"summary":"Query survey results","description":"Read in-app survey response totals, per-question summaries, and recent responses. Query with project_id, environment_id, window=24h|7d|30d, and optional limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Survey results","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SurveyResults"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Survey not found"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"30d"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":25},"description":"Caps `recentResponses`, which carry per-response answers, release, and submission time."}],"x-required-role":"viewer"}},"/query/surveys/{id}/nps":{"get":{"tags":["Session authenticated"],"summary":"Query NPS results","description":"Read Net Promoter Score totals, daily trend, tenant/release/plan segments, and recent responses for a 0-10 survey question. Query with project_id, environment_id, window=24h|7d|30d, and optional question_id, tenant_id, release, plan, and limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"NPS results","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/NpsResults"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Survey not found"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"30d"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"question_id","in":"query","required":false,"schema":{"type":"string","default":"nps"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"release","in":"query","required":false,"schema":{"type":"string"}},{"name":"plan","in":"query","required":false,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/query/message-campaigns/{id}/results":{"get":{"tags":["Session authenticated"],"summary":"Query message campaign results","description":"Read campaign delivery, engagement, conversion, recent event, and opt-out metrics. Query with project_id, environment_id, window=24h|7d|30d, and optional limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Message campaign results","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MessageCampaignResults"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Campaign not found"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"30d"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"x-required-role":"viewer"}},"/query/feedback":{"get":{"tags":["Session authenticated"],"summary":"List feedback submissions","description":"Read recent product feedback submissions for a project environment. Query with project_id, environment_id, optional status (one or more of open|in_progress|reviewed|resolved|archived, comma-separated), assignee_user_id (a console user id or `unassigned`), priority=low|medium|high|urgent, tag, q (substring search over message, path, user id and feedback id), tenant_id, user_id, and optional limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Feedback submissions","content":{"application/json":{"schema":{"type":"object","properties":{"feedback":{"type":"array","items":{"$ref":"#/components/schemas/FeedbackItem"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"One status or a comma-separated list, for example `open,in_progress`.","schema":{"type":"string","examples":["open,in_progress"]}},{"name":"assignee_user_id","in":"query","required":false,"schema":{"type":"string"},"description":"Console user id, or `unassigned`."},{"name":"priority","in":"query","required":false,"schema":{"type":"string","enum":["low","medium","high","urgent"]}},{"name":"tag","in":"query","required":false,"schema":{"type":"string"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"x-required-role":"viewer"}},"/query/feedback/{id}":{"patch":{"tags":["Session authenticated"],"summary":"Triage a feedback submission","description":"Update status, priority, assignee, and tags of a feedback submission. At least one field is required; `priority` and `assignee_user_id` accept null to clear. The assignee must be an active console user.","security":[{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"status":{"type":"string","enum":["open","in_progress","reviewed","resolved","archived"]},"priority":{"type":["string","null"],"enum":["low","medium","high","urgent",null]},"assignee_user_id":{"type":["string","null"]},"tags":{"type":"array","items":{"type":"string","maxLength":40},"maxItems":10}}}}}},"responses":{"200":{"description":"Feedback updated","content":{"application/json":{"schema":{"type":"object","properties":{"feedback":{"$ref":"#/components/schemas/FeedbackItem"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Read token cannot perform mutations (`read_token_is_read_only`); also returned when the caller's console role is below `x-required-role`"},"404":{"description":"Feedback not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"member"}},"/query/feedback/{id}/snapshot":{"get":{"tags":["Session authenticated"],"summary":"Read a feedback snapshot","description":"Return the sanitised, masked DOM snapshot attached to a feedback submission. The markup is re-sanitised on every read (no scripts, event handlers, frames or external URLs) and is meant to be rendered inside a fully sandboxed iframe (`sandbox=\"\"`, no scripts, no same-origin). The response is `application/json`: the markup is the string `snapshot.html`, not a `text/html` document. Returns 404 when the submission has no stored snapshot (none attached, widget `allowScreenshot` off at submission time, dropped by rate limit or quota, or expired by retention). Read tokens may call it within their project/environment scope. Query with project_id and environment_id.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Sanitised snapshot","content":{"application/json":{"schema":{"type":"object","required":["snapshot"],"properties":{"snapshot":{"type":"object","required":["html","bytes","truncated","maskAllText"],"properties":{"html":{"type":"string"},"bytes":{"type":"integer"},"viewport":{"type":["object","null"],"properties":{"width":{"type":"integer"},"height":{"type":"integer"}}},"scroll":{"type":["object","null"],"properties":{"x":{"type":"number"},"y":{"type":"number"}}},"truncated":{"type":"boolean"},"maskAllText":{"type":"boolean"}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Feedback or snapshot not found"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/query/events/retention":{"get":{"tags":["Session authenticated"],"summary":"Query event retention curves","description":"Analyze retention cohorts for a project environment. Cohorts are anchored on each actor's user_profiles.first_seen_at, not the minimum entry_event timestamp inside the queried window. Query with project_id, environment_id, window=24h|7d|30d, optional entry_event (cohort eligibility filter), optional return_event (absent means any event counts as retained), optional period=daily|weekly|monthly, optional intervals=2..12, and optional range_days=1..730 to override the window-derived range for long lookback queries. RETENTION_EVENTS_DAYS remains the installation-level raw-versus-rollup routing threshold; scoped events retention independently controls raw-row deletion and can be shorter or longer. The response reports source=raw|rollup.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/events/click-map":{"get":{"tags":["Session authenticated"],"summary":"Query event click maps","description":"Aggregate opt-in browser click samples by route, safe selector, and grid bucket. Query with project_id, environment_id, route, window=24h|7d|30d, optional selector, tenant_id, user_id, session_id, grid_size=10..100, and limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/events/paths":{"get":{"tags":["Session authenticated"],"summary":"Query event paths","description":"Discover the most common event sequences leading to or from an anchor event for a project environment. At least one of start_event or end_event is required. Query with project_id, environment_id, and one or both of start_event/end_event, plus optional window=24h|7d|30d (default 7d), actor=auto|user|tenant|session|trace (default auto), max_depth=2..8 (default 5), from/to (from must be before to when both given), tenant_id, user_id, session_id, trace_id, segment_id, and limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Most common event path sequences","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["window","generatedAt","scope","range","filters","totals","paths"],"properties":{"window":{"type":"string","enum":["24h","7d","30d"]},"generatedAt":{"type":"string","format":"date-time"},"scope":{"type":"object","properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"}}},"range":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"filters":{"type":"object","properties":{"startEvent":{"type":["string","null"]},"endEvent":{"type":["string","null"]},"tenantId":{"type":["string","null"]},"userId":{"type":["string","null"]},"sessionId":{"type":["string","null"]},"traceId":{"type":["string","null"]},"segmentId":{"type":["string","null"]},"actorType":{"type":"string","enum":["auto","user","tenant","session","trace"]},"pathLength":{"type":"integer"}}},"totals":{"type":"object","properties":{"actors":{"type":"integer","minimum":0},"paths":{"type":"integer","minimum":0},"events":{"type":"integer","minimum":0}}},"paths":{"type":"array","items":{"type":"object","required":["path","actors","occurrences","firstSeenAt","lastSeenAt","sampleEvents"],"properties":{"path":{"type":"array","items":{"type":"string"}},"actors":{"type":"integer","minimum":0},"occurrences":{"type":"integer","minimum":0},"firstSeenAt":{"type":"string","format":"date-time"},"lastSeenAt":{"type":"string","format":"date-time"},"sampleEvents":{"type":"array","items":{"type":"object","required":["id","name","timestamp","actorId","actorType"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"actorId":{"type":"string"},"actorType":{"type":"string","enum":["user","tenant","session","trace"]}}}}}}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Event path query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"start_event","in":"query","required":false,"schema":{"type":"string"},"description":"At least one of start_event/end_event is required."},{"name":"end_event","in":"query","required":false,"schema":{"type":"string"},"description":"At least one of start_event/end_event is required."},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"7d"}},{"name":"actor","in":"query","required":false,"schema":{"type":"string","enum":["auto","user","tenant","session","trace"],"default":"auto"}},{"name":"max_depth","in":"query","required":false,"schema":{"type":"integer","minimum":2,"maximum":8,"default":5}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"session_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"trace_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500}}],"x-required-role":"viewer"}},"/query/sessions":{"get":{"tags":["Session authenticated"],"summary":"Query session list","description":"List sessions (activity grouped by session_id across events, errors, traces, LLM calls, and feedback) for a project environment, newest first by first activity in the window. A session is listed when any of its in-window rows matches user_id, tenant_id, and release. Query with project_id, environment_id, and optional window, session_id, user_id, tenant_id, release, cursor, and limit. The response carries `total`, the number of matching sessions in the window regardless of the cursor, so a client can show a position such as 12 of 340.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Session list","content":{"application/json":{"schema":{"type":"object","required":["data","total"],"properties":{"data":{"type":"array","items":{"type":"object","required":["sessionId","userId","tenantId","release","startedAt","endedAt","durationMs","eventCount","errorCount","traceCount","llmCount","feedbackCount","replayId"],"properties":{"sessionId":{"type":"string"},"userId":{"type":["string","null"]},"tenantId":{"type":["string","null"]},"release":{"type":["string","null"]},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time"},"durationMs":{"type":"integer"},"eventCount":{"type":"integer"},"errorCount":{"type":"integer"},"traceCount":{"type":"integer"},"llmCount":{"type":"integer"},"feedbackCount":{"type":"integer"},"replayId":{"type":["string","null"]}}}},"total":{"type":"integer"},"cursor":{"type":"string"}}}}}},"400":{"description":"Invalid query"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Session listing is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"]},"description":"Defaults to 7d. When session_id is set and window is omitted, the lookup is unbounded in time."},{"name":"session_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"release","in":"query","required":false,"schema":{"type":"string"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from a previous response."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"x-required-role":"viewer"}},"/query/sessions/{sessionId}/timeline":{"get":{"tags":["Session authenticated"],"summary":"Query session timeline","description":"Read one session's mixed, time-ordered timeline across breadcrumbs, events, errors, traces, LLM calls, and feedback for a project environment. Either from/to or center (with before/after) can be used to bound the range; center takes precedence when present. Query with project_id, environment_id, and optional tenant_id, user_id, from, to, center, before, after, types, and limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Session timeline","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["sessionId","scope","range","items","page"],"properties":{"sessionId":{"type":"string"},"scope":{"type":"object","properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"}}},"range":{"type":"object","properties":{"from":{"type":["string","null"],"format":"date-time"},"to":{"type":["string","null"],"format":"date-time"}}},"items":{"type":"array","items":{"type":"object","required":["id","type","timestamp","receivedAt","tenantId","userId","sessionId","traceId","source","release","title","level"],"properties":{"id":{"type":"string"},"type":{"type":"string","enum":["breadcrumb","event","error","trace","llm","feedback"]},"timestamp":{"type":"string","format":"date-time"},"receivedAt":{"type":"string","format":"date-time"},"tenantId":{"type":["string","null"]},"userId":{"type":["string","null"]},"sessionId":{"type":"string"},"traceId":{"type":["string","null"]},"source":{"type":["string","null"]},"release":{"type":["string","null"]},"title":{"type":"string"},"level":{"type":["string","null"]},"data":{"description":"Type-specific payload excerpt."}}}},"page":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"previousCursor":{"type":["string","null"]}}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Session timeline query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"center","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"When present, replaces from/to with a window of `before` seconds earlier to `after` seconds later."},{"name":"before","in":"query","required":false,"schema":{"type":"number","minimum":0,"default":600},"description":"Seconds before `center` to include. Only applied when `center` is set."},{"name":"after","in":"query","required":false,"schema":{"type":"number","minimum":0,"default":120},"description":"Seconds after `center` to include. Only applied when `center` is set."},{"name":"types","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["breadcrumb","event","error","trace","llm","feedback"]}},"style":"form","explode":true,"description":"Repeatable or comma-separated. Defaults to all six types."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100},"description":"Accepted up to 500 by the route; the timeline repository clamps to 1..200 (default 100)."}],"x-required-role":"viewer"}},"/query/replays":{"get":{"tags":["Session authenticated"],"summary":"Query session replay samples","description":"List privacy-safe replay samples for a project environment. Supports saved segment filtering with segment_id plus tenant_id, user_id, event_name, and limit. Results include user, tenant, route, timestamp, and linked event/error context for cohort replay investigation.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/replays/{replayId}":{"get":{"tags":["Session authenticated"],"summary":"Query session replay detail","description":"Read one privacy-safe replay timeline and its linked product event markers. Query with project_id and environment_id; replayId is the path parameter from event or error detail.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/replays/{replayId}/visual":{"get":{"tags":["Session authenticated"],"summary":"Read visual replay chunks","description":"Return one page of the sanitised rrweb event stream of a visual session replay, in chunk order. Requires the `replay` feature (Sigmon Pro / Cloud; 402 on community). Events are re-sanitised on every read and are meant for a sandboxed player (no scripts). Query with project_id and environment_id, optional from_seq (default 0) and limit (1..50, default 10); follow `nextSeq` until it is null to load the whole replay. A page is capped at about 2 MiB of stored chunks (at least one chunk). Returns 404 when no chunks are stored (visual mode off, expired by retention, or never recorded) so clients fall back to the timeline from `GET /query/replays/{replayId}`. Read tokens may call it within their project/environment scope.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Page of sanitised replay chunks","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["replayId","chunks","totalChunks","totalBytes","nextSeq","maskAllText"],"properties":{"replayId":{"type":"string"},"chunks":{"type":"array","items":{"type":"object","required":["seq","events"],"properties":{"seq":{"type":"integer"},"events":{"type":"array","items":{"type":"object","description":"rrweb event (type, timestamp, data)."}}}}},"totalChunks":{"type":"integer"},"totalBytes":{"type":"integer","description":"Stored (compressed) bytes of the whole replay."},"nextSeq":{"type":["integer","null"],"description":"Pass as from_seq for the next page; null on the last page."},"maskAllText":{"type":"boolean"}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/FeatureNotInPlan"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"No visual replay chunks stored for this replay"},"501":{"description":"Visual replay query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"replayId","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"from_seq","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":10}}],"x-required-role":"viewer"}},"/query/entities/tenants":{"get":{"tags":["Session authenticated"],"summary":"List tenant activity","description":"List tenants observed in a project environment, ranked and keyset-paginated by an activity sort. Query with project_id, environment_id, optional window=24h|7d|30d (default 7d), optional search (matches tenant id/traits), optional limit=1..100 (default 50), optional sort, and optional cursor from a previous page's response. The cursor is an opaque base64url-encoded JSON object minted for a specific `sort`; reusing it with a different `sort` value is rejected.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Ranked, paginated tenant activity","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["window","generatedAt","scope","range","tenants"],"properties":{"window":{"type":"string","enum":["24h","7d","30d"]},"generatedAt":{"type":"string","format":"date-time"},"scope":{"type":"object","properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"}}},"range":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"tenants":{"type":"array","items":{"$ref":"#/components/schemas/EntityTenantSummary"}},"cursor":{"type":"string","description":"Present when another page is available."}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Tenant activity query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"7d"}},{"name":"search","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["impact","usage","errors","llm_cost","recent"],"default":"impact"},"description":"Ranking used for both ordering and keyset pagination."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque base64url-encoded JSON keyset cursor `{sort, value, actorId}` returned by a previous page. Must match the request's `sort`."}],"x-required-role":"viewer"}},"/query/entities/tenants/{tenantKey}":{"get":{"tags":["Session authenticated"],"summary":"Query tenant activity detail","description":"Read one tenant's activity summary, top users, and time-ordered signal timeline for a project environment. Query with project_id, environment_id, optional window=24h|7d|30d (default 7d), optional user_id, optional signal_type, optional limit=1..100 (default 50), and optional cursor from a previous page's response. `tenantKey` cannot be the reserved value `_unassigned`.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Tenant activity detail","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["window","generatedAt","scope","range","tenant","topUsers","timeline"],"properties":{"window":{"type":"string","enum":["24h","7d","30d"]},"generatedAt":{"type":"string","format":"date-time"},"scope":{"type":"object","properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"}}},"range":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"tenant":{"$ref":"#/components/schemas/EntityTenantSummary"},"topUsers":{"type":"array","items":{"type":"object","required":["userId","events","errors","traces","llmCalls","llmCostUsd","lastSeenAt"],"properties":{"userId":{"type":"string"},"events":{"type":"integer","minimum":0},"errors":{"type":"integer","minimum":0},"traces":{"type":"integer","minimum":0},"llmCalls":{"type":"integer","minimum":0},"llmCostUsd":{"type":"string"},"lastSeenAt":{"type":"string","format":"date-time"}}}},"timeline":{"type":"array","items":{"type":"object","required":["type","id","timestamp","label"],"properties":{"type":{"type":"string","enum":["event","error","trace","llm"]},"id":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"label":{"type":"string"},"userId":{"type":["string","null"]},"sessionId":{"type":["string","null"]},"traceId":{"type":["string","null"]}},"additionalProperties":true,"description":"Additional fields vary by `type`: events carry eventName; errors carry severity/status/message; traces carry status/durationMs/name; LLM calls carry provider/model/promptName/status/costUsd."}},"cursor":{"type":"string","description":"Present when another timeline page is available."}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Tenant activity query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"tenantKey","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"7d"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"signal_type","in":"query","required":false,"schema":{"type":"string","enum":["event","error","trace","llm"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque base64url-encoded JSON timeline cursor `{timestamp, type, id}` returned by a previous page."}],"x-required-role":"viewer"}},"/query/users":{"get":{"tags":["Session authenticated"],"summary":"List user activity","description":"List users observed in a project environment, ranked and keyset-paginated by an activity sort. Query with project_id, environment_id, optional window=24h|7d|30d (default 7d), optional search (matches user id/traits), optional tenant_id, optional limit=1..100 (default 50), optional sort, and optional cursor from a previous page's response. The cursor is an opaque base64url-encoded JSON object minted for a specific `sort`; reusing it with a different `sort` value is rejected.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Ranked, paginated user activity","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["window","generatedAt","scope","range","users"],"properties":{"window":{"type":"string","enum":["24h","7d","30d"]},"generatedAt":{"type":"string","format":"date-time"},"scope":{"type":"object","properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"}}},"range":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"users":{"type":"array","items":{"$ref":"#/components/schemas/EntityUserSummary"}},"cursor":{"type":"string","description":"Present when another page is available."}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"User activity query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"7d"}},{"name":"search","in":"query","required":false,"schema":{"type":"string"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["impact","usage","errors","llm_cost","recent"],"default":"impact"},"description":"Ranking used for both ordering and keyset pagination."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque base64url-encoded JSON keyset cursor `{sort, value, actorId}` returned by a previous page. Must match the request's `sort`."}],"x-required-role":"viewer"}},"/query/users/{userKey}":{"get":{"tags":["Session authenticated"],"summary":"Query user activity detail","description":"Read one user's activity summary, recent sessions, and time-ordered signal timeline for a project environment. Query with project_id, environment_id, optional window=24h|7d|30d (default 7d), optional tenant_id, optional signal_type, optional limit=1..100 (default 50), and optional cursor from a previous page's response. `userKey` cannot be the reserved value `_anonymous`.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"User activity detail","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["window","generatedAt","scope","range","user","engagement","recentSessions","timeline"],"properties":{"window":{"type":"string","enum":["24h","7d","30d"]},"generatedAt":{"type":"string","format":"date-time"},"scope":{"type":"object","properties":{"projectId":{"type":"string"},"environmentId":{"type":"string"}}},"range":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"user":{"$ref":"#/components/schemas/EntityUserSummary"},"engagement":{"description":"Time on site from `$pageview`/`$pageleave` events in the window; null when page tracking was never instrumented.","oneOf":[{"type":"object","required":["instrumented","sessions","pageviews","totalEngagedMs","medianEngagedMs"],"properties":{"instrumented":{"type":"boolean"},"sessions":{"type":"integer","minimum":0},"pageviews":{"type":"integer","minimum":0},"totalEngagedMs":{"type":["number","null"]},"medianEngagedMs":{"type":["number","null"]}}},{"type":"null"}]},"recentSessions":{"type":"array","items":{"type":"object","required":["sessionId","tenantId","events","errors","traces","llmCalls","llmCostUsd","firstSeenAt","lastSeenAt"],"properties":{"sessionId":{"type":"string"},"tenantId":{"type":["string","null"]},"events":{"type":"integer","minimum":0},"errors":{"type":"integer","minimum":0},"traces":{"type":"integer","minimum":0},"llmCalls":{"type":"integer","minimum":0},"llmCostUsd":{"type":"string"},"firstSeenAt":{"type":"string","format":"date-time"},"lastSeenAt":{"type":"string","format":"date-time"}}}},"timeline":{"type":"array","items":{"type":"object","required":["type","id","timestamp","label"],"properties":{"type":{"type":"string","enum":["event","error","trace","llm"]},"id":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"label":{"type":"string"},"tenantId":{"type":["string","null"]},"sessionId":{"type":["string","null"]},"traceId":{"type":["string","null"]}},"additionalProperties":true,"description":"Additional fields vary by `type`: events carry eventName; errors carry severity/status/message; traces carry status/durationMs/name; LLM calls carry provider/model/promptName/status/costUsd."}},"cursor":{"type":"string","description":"Present when another timeline page is available."}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"User activity query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"userKey","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"7d"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"signal_type","in":"query","required":false,"schema":{"type":"string","enum":["event","error","trace","llm"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque base64url-encoded JSON timeline cursor `{timestamp, type, id}` returned by a previous page."}],"x-required-role":"viewer"}},"/query/errors":{"get":{"tags":["Session authenticated"],"summary":"Query errors","description":"Read project/environment scoped raw error telemetry.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/errors/{id}/source-map-resolution":{"get":{"tags":["Session authenticated"],"summary":"Query error source-map resolution","description":"Resolve one error's stack frames against uploaded source maps for its release, using strict project/environment/release/minified-file matching. Query with project_id and environment_id. The console does not display original source content; this response returns resolved file/line/column locations only.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Source-map resolution result","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["errorId","release","status","frames","unresolvedFrameCount"],"properties":{"errorId":{"type":"string"},"release":{"type":["string","null"]},"status":{"type":"string","enum":["resolved","partially_resolved","unresolved","unavailable"]},"frames":{"type":"array","items":{"type":"object","required":["frameIndex","minifiedFile","minifiedLine","minifiedColumn","originalSource","originalLine","originalColumn","originalName","sourceMapArtifactId"],"properties":{"frameIndex":{"type":"integer","minimum":0},"minifiedFile":{"type":"string"},"minifiedLine":{"type":"integer"},"minifiedColumn":{"type":"integer"},"originalSource":{"type":"string","description":"Original source file path, not file content."},"originalLine":{"type":"integer"},"originalColumn":{"type":"integer"},"originalName":{"type":["string","null"]},"sourceMapArtifactId":{"type":"string"}}}},"unresolvedFrameCount":{"type":"integer","minimum":0}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Error not found"},"501":{"description":"Source-map resolution query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/query/incidents/error-groups/{id}":{"get":{"tags":["Session authenticated"],"summary":"Query error-group incident detail","description":"Read the full incident workspace for one error group: the group record, primary occurrence, priority, source-map resolution status, strongly-related and nearby telemetry context, a linked privacy-safe replay when available, related actor/release ids, assignment, silence state, triage notes, deploy/code context, and linked external issues. Query with project_id, environment_id, and optional error_id to pin the primary occurrence to a specific error instead of the group's latest.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Incident workspace detail","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["group","primaryOccurrence","priority","suggestedPriority","sourceMapResolution","stronglyRelated","nearbyContext","replay","related","incidentNumber","assignedTo","silencedUntil","notes","codeContext","externalIssues"],"properties":{"group":{"$ref":"#/components/schemas/ErrorGroupRecord"},"primaryOccurrence":{"type":"object","additionalProperties":true,"description":"Raw error occurrence backing this incident (the group's latest error, or `error_id` when given)."},"priority":{"type":["string","null"],"enum":["urgent","high","normal","low",null]},"suggestedPriority":{"type":"string","enum":["urgent","high","normal","low"]},"sourceMapResolution":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["cached","none"]},"frameCount":{"type":"integer","minimum":0}}},"stronglyRelated":{"type":"object","required":["items","truncated"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":true}},"truncated":{"type":"boolean"}},"description":"Breadcrumbs, events, errors, traces, and LLM calls tightly correlated to the primary occurrence (same session/trace)."},"nearbyContext":{"type":"object","required":["items","truncated"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":true}},"truncated":{"type":"boolean"}},"description":"Telemetry near the primary occurrence in time but without a direct session/trace link."},"replay":{"type":["object","null"],"additionalProperties":true,"description":"Linked privacy-safe session replay for the primary occurrence, when one exists. Always null on editions without the `replay` feature (community); the payload is omitted server-side."},"related":{"type":"object","properties":{"traceId":{"type":["string","null"]},"sessionId":{"type":["string","null"]},"userId":{"type":["string","null"]},"tenantId":{"type":["string","null"]},"release":{"type":["string","null"]}}},"incidentNumber":{"type":["string","null"]},"assignedTo":{"type":["object","null"],"properties":{"id":{"type":"string"},"email":{"type":"string"}}},"silencedUntil":{"type":["string","null"],"format":"date-time"},"notes":{"type":"array","items":{"type":"object","required":["id","authorEmail","body","createdAt"],"properties":{"id":{"type":"string"},"authorEmail":{"type":"string"},"body":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}},"codeContext":{"type":"object","additionalProperties":true,"description":"Deploy/repository code context: status, linked repository, release commit metadata, and suspected files."},"externalIssues":{"type":"array","items":{"$ref":"#/components/schemas/IncidentExternalLink"}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Incident not found"},"501":{"description":"Incident query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"error_id","in":"query","required":false,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/query/incidents/error-groups/{id}/notes":{"post":{"tags":["Session authenticated"],"summary":"Add an incident triage note","description":"Append an author-attributed triage note to one error-group incident. Query with project_id and environment_id.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Triage note created","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/TriageNoteRecord"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Read token cannot perform mutations (`read_token_is_read_only`); also returned when the caller's console role is below `x-required-role`"},"404":{"description":"Error group not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"501":{"description":"Triage note mutation is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageNoteInput"},"examples":{"default":{"value":{"body":"Rolled back release web@1.4.2, monitoring error rate."}}}}}},"x-required-role":"member"}},"/query/incidents/error-groups/{id}/silence":{"post":{"tags":["Session authenticated"],"summary":"Silence an incident","description":"Silence or unsilence one error-group incident. Send `minutes` as a positive integer to silence for that many minutes from now, or `0`/`null` to clear an existing silence. Query with project_id and environment_id.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Updated error group with new silence state","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ErrorGroupRecord"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Read token cannot perform mutations (`read_token_is_read_only`); also returned when the caller's console role is below `x-required-role`"},"404":{"description":"Error group not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"501":{"description":"Silence mutation is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SilenceIncidentInput"},"examples":{"default":{"value":{"minutes":60}}}}}},"x-required-role":"member"}},"/query/incidents/mttr":{"get":{"tags":["Session authenticated"],"summary":"Query incident MTTR","description":"Read mean-time-to-resolution for error groups resolved within the window, plus the count of groups that resolution was computed from. Query with project_id, environment_id, and optional window=7d|30d (default 7d). Note this route's window enum is narrower than other query routes: only 7d and 30d are accepted, not 24h.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"MTTR rollup","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["mttrMs","resolvedCount","windowDays"],"properties":{"mttrMs":{"type":["number","null"]},"resolvedCount":{"type":"integer","minimum":0},"windowDays":{"type":"integer","enum":[7,30]}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"MTTR query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["7d","30d"],"default":"7d"}}],"x-required-role":"viewer"}},"/query/incidents/error-groups/{id}/external-issues":{"post":{"tags":["Session authenticated"],"summary":"Link an external issue to an incident","description":"Attach a GitHub/GitLab issue URL to a Sigmon error-group incident. Query with project_id and environment_id.","security":[{"sessionCookie":[]}],"responses":{"201":{"description":"External issue linked","content":{"application/json":{"schema":{"type":"object","properties":{"link":{"$ref":"#/components/schemas/IncidentExternalLink"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Read token cannot perform mutations (`read_token_is_read_only`); also returned when the caller's console role is below `x-required-role`"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["provider","externalKey","title","url"],"properties":{"integrationId":{"type":["string","null"]},"provider":{"type":"string","enum":["github","gitlab"]},"externalKey":{"type":"string"},"title":{"type":"string"},"url":{"type":"string","format":"uri"},"state":{"type":"string","default":"open"}}}}}},"x-required-role":"member"}},"/query/incidents/error-groups/{id}/external-issues/draft":{"post":{"tags":["Session authenticated"],"summary":"Create an external issue draft URL","description":"Build a prefilled GitHub/GitLab new-issue URL from a Sigmon incident. Query with project_id and environment_id.","security":[{"sessionCookie":[]}],"responses":{"201":{"description":"Issue draft URL","content":{"application/json":{"schema":{"type":"object","properties":{"draft":{"$ref":"#/components/schemas/IncidentIssueDraft"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Read token cannot perform mutations (`read_token_is_read_only`); also returned when the caller's console role is below `x-required-role`"},"404":{"description":"Code integration not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":[],"properties":{"integrationId":{"type":"string"},"incidentUrl":{"type":"string","format":"uri"}}}}}},"x-required-role":"member"}},"/query/llm-calls":{"get":{"tags":["Session authenticated"],"summary":"Query LLM calls","description":"Read project/environment scoped LLM call telemetry. Each call carries costUsd (decimal string) and costSource: `client` when the caller sent the cost, `catalog` when the worker estimated it from the built-in pricing catalog, `project_override` when it used the project's own price table, or `unknown` when neither was available (costUsd is then 0 and must not be read as free).","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/llm-calls/{id}/content":{"get":{"tags":["Session authenticated"],"summary":"Read LLM call content","description":"Read the full prompt and response captured for one call. Requires a console session with the member or admin role: viewers get 403 role_required and read tokens get 403 read_token_not_allowed. Answers 404 llm_content_not_found when the call is outside the project and environment, sent no content, or its content expired.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Captured content","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["llmCallId","inputContent","outputContent","inputTruncated","outputTruncated"],"properties":{"llmCallId":{"type":"string"},"inputContent":{"type":["string","null"]},"outputContent":{"type":["string","null"]},"inputTruncated":{"type":"boolean"},"outputTruncated":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid query"},"401":{"description":"Not authenticated"},"403":{"description":"Below the member role, or called with a read token; also returned when the caller's console role is below `x-required-role`"},"404":{"description":"No content for this call in this scope"},"501":{"description":"Query method unavailable"},"503":{"description":"Query unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"x-required-role":"member"}},"/query/llm/summary":{"get":{"tags":["Session authenticated"],"summary":"Query LLM summary","description":"Read a single-window LLM rollup for a project environment: call count, failed-call count, total cost, average token count, average latency, and p95 latency. Query with project_id, environment_id, and optional window=24h|7d|30d (default 24h).","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"LLM summary rollup","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["calls","failedCalls","costUsd","estimatedCostUsd","unpricedCalls","avgTokens","avgLatencyMs","p95LatencyMs"],"properties":{"calls":{"type":"integer","minimum":0},"failedCalls":{"type":"integer","minimum":0},"costUsd":{"type":"string","description":"Decimal string, e.g. \"1.2345\"."},"estimatedCostUsd":{"type":"string","description":"Part of costUsd estimated by the worker from the LLM pricing catalog or a project price override (cost_source = catalog or project_override). Decimal string."},"unpricedCalls":{"type":"integer","minimum":0,"description":"Calls with no client cost and no catalog price (cost_source = unknown); they add 0 to costUsd."},"avgTokens":{"type":["number","null"]},"avgLatencyMs":{"type":["number","null"]},"p95LatencyMs":{"type":["number","null"]}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"LLM summary query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"24h"}}],"x-required-role":"viewer"}},"/query/llm/by-tenant":{"get":{"tags":["Session authenticated"],"summary":"Query LLM usage by tenant","description":"Read per-tenant LLM rollups for a project environment: call count, failed-call count, cost, average token count, average latency, and p95 latency per tenant. Query with project_id, environment_id, and optional window=24h|7d|30d (default 24h).","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Per-tenant LLM rollups","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["tenantId","calls","failedCalls","costUsd","estimatedCostUsd","unpricedCalls","avgTokens","avgLatencyMs","p95LatencyMs"],"properties":{"tenantId":{"type":"string"},"calls":{"type":"integer","minimum":0},"failedCalls":{"type":"integer","minimum":0},"costUsd":{"type":"string"},"estimatedCostUsd":{"type":"string","description":"Part of costUsd estimated by the worker from the LLM pricing catalog or a project price override (cost_source = catalog or project_override). Decimal string."},"unpricedCalls":{"type":"integer","minimum":0,"description":"Calls with no client cost and no catalog price (cost_source = unknown); they add 0 to costUsd."},"avgTokens":{"type":["number","null"]},"avgLatencyMs":{"type":["number","null"]},"p95LatencyMs":{"type":["number","null"]}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"LLM by-tenant query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"24h"}}],"x-required-role":"viewer"}},"/query/llm/by-prompt":{"get":{"tags":["Session authenticated"],"summary":"Query LLM usage by prompt","description":"Read per-prompt LLM rollups for a project environment: model, call count, failed-call count, cost, average token count, average latency, and p95 latency per prompt_name/model pair. Query with project_id, environment_id, and optional window=24h|7d|30d (default 24h).","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Per-prompt LLM rollups","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["promptName","model","calls","failedCalls","costUsd","estimatedCostUsd","unpricedCalls","avgTokens","avgLatencyMs","p95LatencyMs"],"properties":{"promptName":{"type":"string"},"model":{"type":"string"},"calls":{"type":"integer","minimum":0},"failedCalls":{"type":"integer","minimum":0},"costUsd":{"type":"string"},"estimatedCostUsd":{"type":"string","description":"Part of costUsd estimated by the worker from the LLM pricing catalog or a project price override (cost_source = catalog or project_override). Decimal string."},"unpricedCalls":{"type":"integer","minimum":0,"description":"Calls with no client cost and no catalog price (cost_source = unknown); they add 0 to costUsd."},"avgTokens":{"type":["number","null"]},"avgLatencyMs":{"type":["number","null"]},"p95LatencyMs":{"type":["number","null"]}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"LLM by-prompt query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"24h"}}],"x-required-role":"viewer"}},"/query/llm/cost-by-model":{"get":{"tags":["Session authenticated"],"summary":"Query LLM cost by model","description":"Read a time-bucketed LLM cost series broken down by model for a project environment. Query with project_id, environment_id, and optional window=24h|7d|30d (default 24h).","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Bucketed cost-by-model series","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["buckets","series"],"properties":{"buckets":{"type":"array","items":{"type":"string","format":"date-time"}},"series":{"type":"array","items":{"type":"object","required":["model","costs","estimatedCostUsd","unpricedCalls"],"properties":{"model":{"type":"string"},"costs":{"type":"array","items":{"type":"string"},"description":"Decimal-string costs aligned index-for-index with `buckets`."},"estimatedCostUsd":{"type":"string","description":"Window total of this model's cost that was estimated from the LLM pricing catalog."},"unpricedCalls":{"type":"integer","minimum":0,"description":"Calls of this model in the window with no client cost and no catalog price."}}}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"LLM cost-by-model query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"24h"}}],"x-required-role":"viewer"}},"/query/traces":{"get":{"tags":["Session authenticated"],"summary":"Query traces","description":"Read project/environment scoped trace telemetry. Supports trace drilldown filters such as trace_id, trace_name, status, tenant_id, user_id, session_id, from, to, limit, and cursor.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/traces/{id}/spans":{"get":{"tags":["Session authenticated"],"summary":"List trace spans","description":"List spans for one trace using cursor pagination. `trace_id`, if given as a query parameter, must match the `id` path parameter or the request is rejected. Query with project_id, environment_id, and optional tenant_id, user_id, session_id, trace_id, from, to, limit=1..500 (default 50), and cursor from a previous page's response.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Paginated trace spans","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["id","projectId","environmentId","tenantId","userId","sessionId","traceId","timestamp","receivedAt","source","release","parentSpanId","name","status","startedAt","endedAt","durationMs"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"environmentId":{"type":"string"},"tenantId":{"type":["string","null"]},"userId":{"type":["string","null"]},"sessionId":{"type":["string","null"]},"traceId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"receivedAt":{"type":"string","format":"date-time"},"source":{"type":["string","null"]},"release":{"type":["string","null"]},"metadata":{},"parentSpanId":{"type":["string","null"]},"name":{"type":"string"},"status":{"type":"string"},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"durationMs":{"type":["number","null"]},"input":{},"output":{},"error":{},"costUsd":{"type":["string","null"]}}}},"cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Trace span query is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"tenant_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"session_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"trace_id","in":"query","required":false,"schema":{"type":"string"},"description":"If given, must equal the `id` path parameter."},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/query/apm/endpoints":{"get":{"tags":["Session authenticated"],"summary":"Query APM endpoints","description":"Read endpoint-level APM rollups for a project environment, including throughput, errors, error rate, p50/p95/p99 latency, average latency, Apdex, and last seen timestamp. Query with project_id, environment_id, window=24h|7d|30d, and optional limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/apm/service-map":{"get":{"tags":["Session authenticated"],"summary":"Query APM service map","description":"Read span-derived service dependency edges for a project environment, including source, target, dependency type, span count, distinct trace count, errors, error rate, average latency, p95 latency, and last seen timestamp. Query with project_id, environment_id, window=24h|7d|30d, and optional limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/apm/web-vitals":{"get":{"tags":["Session authenticated"],"summary":"Query APM Web Vitals","description":"Read browser Web Vital rollups for a project environment, including p75 by metric and route, sample counts, rating counts, latest release p75, previous release p75, and regression percent. Query with project_id, environment_id, window=24h|7d|30d, and optional limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/query/apm/profiles":{"get":{"tags":["Session authenticated"],"summary":"Query APM runtime profiles","description":"Read runtime CPU and memory profile rollups for a project environment, including profile counts, CPU/memory totals, recent profiles, and hot functions. Query with project_id, environment_id, window=24h|7d|30d, and optional limit.","security":[{"sessionCookie":[]},{"readToken":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/alerts/events":{"get":{"tags":["Session authenticated"],"summary":"List alert events","description":"List triggered alert events for a project environment, most recent first. Query with project_id, environment_id, and optional limit.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Alert events","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AlertEventRecord"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Alert repository is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}}],"x-required-role":"viewer"}},"/alerts/events/{id}":{"get":{"tags":["Session authenticated"],"summary":"Read an alert event","description":"Read one alert event by id.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Alert event","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AlertEventRecord"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Alert event not found"},"501":{"description":"Alert repository is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/alerts/events/{id}/triage":{"patch":{"tags":["Session authenticated"],"summary":"Triage an alert event","description":"Update an alert event's status (acknowledge, snooze, or resolve) and optionally attach a triage note. `snoozedUntil` is required when `status` is `snoozed`.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Updated alert event","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/AlertEventRecord"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Alert event not found"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"501":{"description":"Alert repository is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertEventTriagePatch"},"examples":{"default":{"value":{"status":"acknowledged"}}}}}},"x-required-role":"member"}},"/alerts/suggestions":{"get":{"tags":["Session authenticated"],"summary":"List alert rule suggestions","description":"Return heuristic alert rule suggestions for a project environment based on recent critical errors, error counts, error rate, trace p95 latency, LLM cost, and dead-letter activity. Suggestions with an already-active matching rule are omitted. Query with project_id and environment_id.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Alert rule suggestions","content":{"application/json":{"schema":{"type":"object","required":["suggestions"],"properties":{"suggestions":{"type":"array","items":{"$ref":"#/components/schemas/AlertSuggestion"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"Alert repository is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","required":true,"schema":{"type":"string"}}],"x-required-role":"viewer"}},"/system/health":{"get":{"tags":["Session authenticated"],"summary":"Read system health","description":"Read API, worker, Postgres, Redis, queue, freshness, retention, and backup status. `queues.telemetry.oldestWaitingAgeSeconds` is the age of the oldest job still waiting in the ingestion queue (null when nothing waits); at 5 minutes the queue and overall status become `degraded`, at 30 minutes `unhealthy`.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Request succeeded"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"x-required-role":"viewer"}},"/system/health/history":{"get":{"tags":["Session authenticated"],"summary":"Read system health history","description":"Read recent system health samples (Postgres/Redis latency and telemetry queue depth) captured on an interval, most recent first. Query with optional limit (1-480, default 60).","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"System health samples","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SystemHealthSample"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"501":{"description":"System health history is not available"},"503":{"$ref":"#/components/responses/Unavailable"}},"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":480,"default":60}}],"x-required-role":"viewer"}},"/system/actions/doctor":{"post":{"tags":["Session authenticated"],"summary":"Run system doctor","description":"Admin-only read-only self-check that evaluates the current SignalMonitor installation health and returns an operator summary.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"System action completed or skipped","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemActionResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/system/actions/backup":{"post":{"tags":["Session authenticated"],"summary":"Trigger manual backup","description":"Admin-only action that queues the same backup workflow used by the scheduler. The worker runs it asynchronously under the backup advisory lock.","security":[{"sessionCookie":[]}],"responses":{"202":{"description":"Backup job accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemBackupActionResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}},"/system/actions/retention":{"post":{"tags":["Session authenticated"],"summary":"Trigger manual retention","description":"Admin-only action that runs the same telemetry, dead-letter, and source-map retention workflow used by the scheduler.","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"System action completed or skipped","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemActionResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"423":{"$ref":"#/components/responses/InstanceReadOnly"},"429":{"$ref":"#/components/responses/TooManyRequests"},"501":{"$ref":"#/components/responses/Unavailable"},"503":{"$ref":"#/components/responses/Unavailable"}},"x-required-role":"admin"}}}}